Merge lp:~akopytov/percona-xtrabackup/bug1130627-2.0 into lp:percona-xtrabackup/2.0

Proposed by Alexey Kopytov
Status: Merged
Approved by: Sergei Glushchenko
Approved revision: no longer in the source branch.
Merged at revision: 512
Proposed branch: lp:~akopytov/percona-xtrabackup/bug1130627-2.0
Merge into: lp:percona-xtrabackup/2.0
Diff against target: 351 lines (+183/-55)
3 files modified
innobackupex (+38/-17)
src/xtrabackup.cc (+71/-38)
test/t/bug1130627.sh (+74/-0)
To merge this branch: bzr merge lp:~akopytov/percona-xtrabackup/bug1130627-2.0
Reviewer Review Type Date Requested Status
Sergei Glushchenko (community) g2 Approve
Review via email: mp+151895@code.launchpad.net

Description of the change

    Bug #1130627: Can't backup individual partitions

    The bug is a regression introduced in 2.0.5 by the fix for bug
    #711166. The fix introduced partition suffix ('#P#...') trimming in
    tables names before checking them against regular expressions specified
    by the --include option in innobackupex or the --tables option in
    xtrabackup. Which made impossible partial backups of partitioned tables.

    Fixed in both innobackupex and xtrabackup by first checking the table
    name without the suffix trimmed, and then repeating the check with the
    suffix trimmed if the former check fails.

    This patch also fixes bug #1131084 "Unneccessary/debug print in
    xtrabackup output" and a few other minor issues introduced by the fix
    for bug #711166.

http://jenkins.percona.com/view/XtraBackup/job/percona-xtrabackup-2.0-param/357/

To post a comment you must log in.
Revision history for this message
Sergei Glushchenko (sergei.glushchenko) wrote :

Alexey,

* get_table_name_with_part_suffic - is it a typo?
* innobackupex change affects only --include option (which is regex) and
  doesn't affects --databases option, i.e. with --databases option individual
  partitions still cannot be backed up
* while xtrabackup change affects both --tables and --tables-file (one with regexp, another one without)
  which looks to me as kind of inconsistency
* check_if_table_matches_regexps doesn't look like a good name since it not
  only matches against regexps, but also against table names from --tables-file
* would also be nice to have testcases which take a backup only of some partitions
  with different combinations of options

review: Needs Fixing (g2)
Revision history for this message
Alexey Kopytov (akopytov) wrote :

Hi Sergei,

On Thu, 07 Mar 2013 05:26:19 -0000, Sergei Glushchenko wrote:
> Review: Needs Fixing g2
>
> Alexey,
>
> * get_table_name_with_part_suffic - is it a typo?

Yes, thanks.

> * innobackupex change affects only --include option (which is regex) and
> doesn't affects --databases option, i.e. with --databases option individual
> partitions still cannot be backed up

Yes, I've made all the necessary corrections for --databases and
--tables-file, but --databases is currently broken due to bug #569387.
So the corresponding part of the test case should be uncommented once fixed.

> * while xtrabackup change affects both --tables and --tables-file (one with regexp, another one without)
> which looks to me as kind of inconsistency

Yep, it should now be consistent.

> * check_if_table_matches_regexps doesn't look like a good name since it not
> only matches against regexps, but also against table names from --tables-file

Agree, renamed to check_if_table_matches_filters()

> * would also be nice to have testcases which take a backup only of some partitions
> with different combinations of options
>

Added, with the caveat re. --databases mentioned above.

I'm currently waiting on Jenkins runs, will update the MP when they are
done.

Revision history for this message
Alexey Kopytov (akopytov) wrote :
Revision history for this message
Sergei Glushchenko (sergei.glushchenko) wrote :

Alexey,

Everything looks good except I don't see testcase, which you mentioned as added. Probably you forget to bzr add them?

Revision history for this message
Sergei Glushchenko (sergei.glushchenko) :
review: Needs Fixing (g2)
Revision history for this message
Alexey Kopytov (akopytov) wrote :

Whoops :) Good catch!

Revision history for this message
Alexey Kopytov (akopytov) wrote :
Revision history for this message
Sergei Glushchenko (sergei.glushchenko) wrote :

Approve

review: Approve (g2)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'innobackupex'
--- innobackupex 2013-02-04 07:32:47 +0000
+++ innobackupex 2013-03-07 11:50:26 +0000
@@ -1137,12 +1137,14 @@
1137 foreach $file (@list) {1137 foreach $file (@list) {
1138 next unless check_if_required($subdir, $file);1138 next unless check_if_required($subdir, $file);
1139 if($option_include) {1139 if($option_include) {
1140 my $table_name;1140 my $table = get_table_name($file);
11411141 my $table_part = get_table_name_with_part_suffix($file);
1142 $table_name = get_table_name($file);1142
11431143 if (!("$subdir.$table_part" =~ /$option_include/ ||
1144 if (!("$subdir.$table_name" =~ /$option_include/)) {1144 "$subdir.$table" =~ /$option_include/)) {
1145 print STDERR "'$file' is skipped.\n";1145 if ($print_each_file) {
1146 print STDERR "'$file' is skipped.\n";
1147 }
1146 next;1148 next;
1147 }1149 }
1148 }1150 }
@@ -2177,13 +2179,18 @@
2177 next unless check_if_required($database, $file);2179 next unless check_if_required($database, $file);
21782180
2179 if($option_include) {2181 if($option_include) {
2180 my $table_name = get_table_name($file);2182 my $table = get_table_name($file);
2181 if (!("$database.$table_name" =~ /$option_include/)) {2183 my $table_part = get_table_name_with_part_suffix($file);
2182 print STDERR "$database.$file is skipped because it does not match $option_include.\n";2184
2183 next;2185 if (!("$database.$table_part" =~ /$option_include/ ||
2184 }2186 "$database.$table" =~ /$option_include/)) {
2187
2188 if ($print_each_file) {
2189 print STDERR "$database.$file is skipped because it does not match '$option_include'.\n";
2190 }
2191 next;
2192 }
2185 }2193 }
2186
2187 2194
2188 if ($print_each_file) {2195 if ($print_each_file) {
2189 print STDERR "$prefix Backing up file '$source_dir/$database/$file'\n";2196 print STDERR "$prefix Backing up file '$source_dir/$database/$file'\n";
@@ -2519,6 +2526,17 @@
2519# 1 table name2526# 1 table name
2520#2527#
2521sub get_table_name {2528sub get_table_name {
2529 my $table;
2530
2531 $table = get_table_name_with_part_suffix($_[0]);
2532 # trim partition suffix
2533 $table = (split('#P#', $table))[0];
2534
2535 return $table;
2536}
2537
2538# Like get_table_name(), but keeps the partition suffix if present
2539sub get_table_name_with_part_suffix {
2522 my $table_path = shift;2540 my $table_path = shift;
2523 my $filename;2541 my $filename;
2524 my $table;2542 my $table;
@@ -2527,8 +2545,6 @@
2527 $filename = (reverse(split(/\//, $table_path)))[0];2545 $filename = (reverse(split(/\//, $table_path)))[0];
2528 # get name of the table by removing file suffix2546 # get name of the table by removing file suffix
2529 $table = (split(/\./, $filename))[0];2547 $table = (split(/\./, $filename))[0];
2530 # and partition suffix
2531 $table = (split('#P#', $table))[0];
25322548
2533 return $table;2549 return $table;
2534}2550}
@@ -2546,14 +2562,16 @@
2546 my $db_count = scalar keys %databases_list;2562 my $db_count = scalar keys %databases_list;
2547 my $tbl_count = scalar keys %table_list;2563 my $tbl_count = scalar keys %table_list;
2548 my $table;2564 my $table;
2565 my $table_part;
25492566
2550 if ( $db_count == 0 && $tbl_count == 0 ) {2567 if ( $db_count == 0 && $tbl_count == 0 ) {
2551 # No databases defined with --databases option, include all databases,2568 # No databases defined with --databases option, include all databases,
2552 # and no tables defined with --tables-file option, include all tables.2569 # and no tables defined with --tables-file option, include all tables.
2553 return 1;2570 return 1;
2554 }2571 }
2555 else {2572 else {
2556 if ( $table_path ) {2573 if ( $table_path ) {
2574 $table_part = get_table_name_with_part_suffix($table_path);
2557 $table = get_table_name($table_path);2575 $table = get_table_name($table_path);
2558 }2576 }
2559 }2577 }
@@ -2564,7 +2582,9 @@
2564 if (defined $table_path) {2582 if (defined $table_path) {
2565 my $db_hash = $databases_list{$db};2583 my $db_hash = $databases_list{$db};
2566 $db_count = keys %$db_hash;2584 $db_count = keys %$db_hash;
2567 if ($db_count > 0 && ! defined $databases_list{$db}->{$table}) {2585 if ($db_count > 0 &&
2586 !defined $databases_list{$db}->{$table_part} &&
2587 !defined $databases_list{$db}->{$table}) {
2568 # --databases option specified, but table is not included2588 # --databases option specified, but table is not included
2569 return 0;2589 return 0;
2570 }2590 }
@@ -2581,7 +2601,8 @@
2581 # Filter for --tables-file.2601 # Filter for --tables-file.
2582 if ( $tbl_count ) {2602 if ( $tbl_count ) {
2583 return 0 unless exists $table_list{$db};2603 return 0 unless exists $table_list{$db};
2584 return 0 if $table && !$table_list{$db}->{$table};2604 return 0 if $table && !$table_list{$db}->{$table_part} &&
2605 !$table_list{$db}->{$table};
2585 }2606 }
25862607
2587 return 1; # backup the table2608 return 1; # backup the table
25882609
=== modified file 'src/xtrabackup.cc'
--- src/xtrabackup.cc 2013-03-01 06:54:51 +0000
+++ src/xtrabackup.cc 2013-03-07 11:50:26 +0000
@@ -2971,6 +2971,46 @@
2971}2971}
29722972
2973/************************************************************************2973/************************************************************************
2974Checks if a given table name matches any of specifications in the --tables or
2975--tables-file options.
2976
2977@return TRUE on match. */
2978static my_bool
2979check_if_table_matches_filters(const char *name)
2980{
2981 int regres;
2982 int i;
2983 xtrabackup_tables_t* table;
2984
2985 if (xtrabackup_tables) {
2986
2987 regres = REG_NOMATCH;
2988
2989 for (i = 0; i < tables_regex_num; i++) {
2990 regres = xb_regexec(&tables_regex[i], name, 1,
2991 tables_regmatch, 0);
2992 if (regres != REG_NOMATCH) {
2993
2994 return(TRUE);
2995 }
2996 }
2997 }
2998
2999 if (xtrabackup_tables_file) {
3000
3001 XB_HASH_SEARCH(name_hash, tables_hash, ut_fold_string(name),
3002 table, (void) 0,
3003 !strcmp(table->name, name));
3004 if (table) {
3005
3006 return(TRUE);
3007 }
3008 }
3009
3010 return(FALSE);
3011}
3012
3013/************************************************************************
2974Checks if a table specified as a path should be skipped from backup3014Checks if a table specified as a path should be skipped from backup
2975based on the --tables or --tables-file options.3015based on the --tables or --tables-file options.
29763016
@@ -3009,37 +3049,24 @@
3009 }3049 }
3010 buf[dbname_len - 1] = 0;3050 buf[dbname_len - 1] = 0;
30113051
3052 /* For partitioned tables first try to match against the regexp
3053 without truncating the #P#... suffix so we can backup individual
3054 partitions with regexps like '^test[.]t#P#p5' */
3055 if (check_if_table_matches_filters(buf)) {
3056
3057 return(FALSE);
3058 }
3012 if ((eptr = strstr(buf, "#P#")) != NULL) {3059 if ((eptr = strstr(buf, "#P#")) != NULL) {
3060
3013 *eptr = 0;3061 *eptr = 0;
3014 }3062
30153063 if (check_if_table_matches_filters(buf)) {
3016 if (xtrabackup_tables) {3064
3017 int regres = REG_NOMATCH;3065 return(FALSE);
3018 int i;3066 }
3019 for (i = 0; i < tables_regex_num; i++) {3067 }
3020 regres = xb_regexec(&tables_regex[i], buf, 1,3068
3021 tables_regmatch, 0);3069 return(TRUE);
3022 if (regres != REG_NOMATCH) {
3023 break;
3024 }
3025 }
3026 if (regres == REG_NOMATCH) {
3027 return(TRUE);
3028 }
3029 }
3030
3031 if (xtrabackup_tables_file) {
3032 xtrabackup_tables_t* table;
3033
3034 XB_HASH_SEARCH(name_hash, tables_hash, ut_fold_string(buf),
3035 table, (void) 0,
3036 !strcmp(table->name, buf));
3037 if (!table) {
3038 return(TRUE);
3039 }
3040 }
3041
3042 return(FALSE);
3043}3070}
30443071
3045/***********************************************************************3072/***********************************************************************
@@ -3313,8 +3340,7 @@
33133340
3314 if ((!trx_sys_sys_space(node->space->id))3341 if ((!trx_sys_sys_space(node->space->id))
3315 && check_if_skip_table(node->name, "ibd")) {3342 && check_if_skip_table(node->name, "ibd")) {
3316 printf("[%02u] Skipping %s.\n",3343 msg("[%02u] Skipping %s.\n", thread_n, node->name);
3317 thread_n, node->name);
3318 return(FALSE);3344 return(FALSE);
3319 }3345 }
33203346
@@ -4337,6 +4363,8 @@
43374363
4338 p = xtrabackup_tables;4364 p = xtrabackup_tables;
4339 for (i=0; i < tables_regex_num; i++) {4365 for (i=0; i < tables_regex_num; i++) {
4366 int rc;
4367
4340 next = strchr(p, ',');4368 next = strchr(p, ',');
4341 ut_a(next || i == tables_regex_num - 1);4369 ut_a(next || i == tables_regex_num - 1);
43424370
@@ -4344,10 +4372,18 @@
4344 if (i != tables_regex_num - 1)4372 if (i != tables_regex_num - 1)
4345 *(next - 1) = '\0';4373 *(next - 1) = '\0';
43464374
4347 xb_regerror(xb_regcomp(&tables_regex[i], p,4375 rc = xb_regcomp(&tables_regex[i], p,
4348 REG_EXTENDED),4376 REG_EXTENDED);
4349 &tables_regex[i], errbuf, sizeof(errbuf));4377
4350 msg("xtrabackup: tables regcomp(%s): %s\n", p, errbuf);4378 if (rc) {
4379
4380 xb_regerror(rc, &tables_regex[i], errbuf,
4381 sizeof(errbuf));
4382 msg("xtrabackup: regcomp(%s) failed: %s\n",
4383 p, errbuf);
4384
4385 exit(EXIT_FAILURE);
4386 }
43514387
4352 if (i != tables_regex_num - 1)4388 if (i != tables_regex_num - 1)
4353 *(next - 1) = ',';4389 *(next - 1) = ',';
@@ -4394,9 +4430,6 @@
43944430
4395 HASH_INSERT(xtrabackup_tables_t, name_hash, tables_hash,4431 HASH_INSERT(xtrabackup_tables_t, name_hash, tables_hash,
4396 ut_fold_string(table->name), table);4432 ut_fold_string(table->name), table);
4397
4398 msg("xtrabackup: table '%s' is registered to the "
4399 "list.\n", table->name);
4400 }4433 }
4401 }4434 }
4402}4435}
44034436
=== added file 'test/t/bug1130627.sh'
--- test/t/bug1130627.sh 1970-01-01 00:00:00 +0000
+++ test/t/bug1130627.sh 2013-03-07 11:50:26 +0000
@@ -0,0 +1,74 @@
1########################################################################
2# Bug #1130627: Can't backup individual partitions
3########################################################################
4
5. inc/common.sh
6. inc/ib_part.sh
7
8start_server --innodb_file_per_table
9
10require_partitioning
11
12run_cmd $MYSQL $MYSQL_ARGS test <<EOF
13CREATE TABLE t_innodb (
14 i INT NOT NULL AUTO_INCREMENT,
15 c CHAR(10) DEFAULT NULL,
16 PRIMARY KEY (i)
17) ENGINE=InnoDB
18/*!50100 PARTITION BY HASH (i)
19PARTITIONS 10 */;
20
21CREATE TABLE t_myisam (
22 i INT NOT NULL AUTO_INCREMENT,
23 c CHAR(10) DEFAULT NULL,
24 PRIMARY KEY (i)
25) ENGINE=MyISAM
26/*!50100 PARTITION BY HASH (i)
27PARTITIONS 10 */;
28EOF
29
30# Force a checkpoint
31stop_server
32start_server --innodb_file_per_table
33
34# Test that specifying partitions with --include works
35innobackupex --no-timestamp --include='^test.*#P#p5' $topdir/backup
36innobackupex --apply-log $topdir/backup
37
38file_cnt=`ls $topdir/backup/test | wc -l`
39
40test "$file_cnt" -eq 3
41
42test -f $topdir/backup/test/t_innodb#P#p5.ibd
43test -f $topdir/backup/test/t_myisam#P#p5.MYD
44test -f $topdir/backup/test/t_myisam#P#p5.MYI
45
46rm -rf $topdir/backup
47
48# Test that specifying partitions with --databases works
49# TODO: uncomment when bug #569387 is fixed
50
51# innobackupex --no-timestamp \
52# --databases='test.t_myisam#P#p5 test.t_innodb#P#p5' $topdir/backup
53# innobackupex --apply-log $topdir/backup
54
55# test "$file_cnt" -eq 3
56# test -f $topdir/backup/test/t_innodb#P#p5.ibd
57# test -f $topdir/backup/test/t_myisam#P#p5.MYD
58# test -f $topdir/backup/test/t_myisam#P#p5.MYI
59
60# rm -rf $topdir/backup
61
62# Test that specifying partitions with --tables-file works
63cat >$topdir/tables_file <<EOF
64test.t_myisam#P#p5
65test.t_innodb#P#p5
66EOF
67innobackupex --no-timestamp --tables-file=$topdir/tables_file $topdir/backup
68innobackupex --apply-log $topdir/backup
69
70test "$file_cnt" -eq 3
71test -f $topdir/backup/test/t_myisam#P#p5.MYD
72test -f $topdir/backup/test/t_myisam#P#p5.MYI
73
74rm -rf $topdir/backup

Subscribers

People subscribed via source and target branches