diff --git a/bin/pt-table-checksum b/bin/pt-table-checksum index 15fe63b9..737b21f9 100755 --- a/bin/pt-table-checksum +++ b/bin/pt-table-checksum @@ -6096,9 +6096,6 @@ sub main { if ( defined $chunk_index && !$chunk_index ) { $o->save_error('--chunk-index cannot be an empty string'); } - else { - $chunk_index = lc $chunk_index; - } if ( defined $n_chunk_index_cols && (!$n_chunk_index_cols || $n_chunk_index_cols =~ m/[^\d]/ @@ -6684,7 +6681,7 @@ sub main { die "Cannot determine the key_len of the chunk index " . "because MySQL chose " . ($expl->{key} ? "the $expl->{key}" : "no") . " index " - . "rather than the " . $nibble_iter->nibble_index() + . "instead of the " . $nibble_iter->nibble_index() . " index for the first lower boundary statement. " . "See --[no]check-plan in the documentation for more " . "information."; @@ -7142,10 +7139,9 @@ sub nibble_is_safe { if ( !$tbl->{warned}->{not_using_chunk_index}++ && $o->get('quiet') < 2 ) { warn ts("Skipping chunk " . $nibble_iter->nibble_number() - . " of table $tbl->{db}.$tbl->{tbl} because MySQL chose " + . " of $tbl->{db}.$tbl->{tbl} because MySQL chose " . ($expl->{key} ? "the $expl->{key}" : "no") . " index " - . " instead of the " . $nibble_iter->nibble_index() . "index. " - . "This warning will not be printed again for this table.\n"); + . " instead of the " . $nibble_iter->nibble_index() . "index.\n"); } return 0; # not safe } @@ -7164,14 +7160,13 @@ sub nibble_is_safe { if ( !$tbl->{warned}->{oversize_chunk}++ && $o->get('quiet') < 2 ) { warn ts("Skipping chunk " . $nibble_iter->nibble_number() - . " of table $tbl->{db}.$tbl->{tbl} because it is oversized. " + . " of $tbl->{db}.$tbl->{tbl} because it is oversized. " . "The current chunk size limit is " . ($tbl->{chunk_size} * $limit) . " rows (chunk size=$tbl->{chunk_size}" . " * chunk size limit=$limit), but MySQL estimates " . "that there are " . ($expl->{rows} || 0) - . " rows in the chunk." - . " This warning will not be printed again for this table.\n"); + . " rows in the chunk.\n"); } return 0; # not safe } @@ -7185,12 +7180,11 @@ sub nibble_is_safe { if ( !$tbl->{warned}->{key_len}++ && $o->get('quiet') < 2 ) { warn ts("Skipping chunk " . $nibble_iter->nibble_number() - . " of table $tbl->{db}.$tbl->{tbl} because MySQL chose " - . "to use only " . ($expl->{key_len} || 0) . " bytes " - . "of the " . ($expl->{key} || '?') . " index. " - . "See --[no]check-plan in the documentation for " - . "more information. This warning will not be printed " - . "again for this table.\n"); + . " of $tbl->{db}.$tbl->{tbl} because MySQL used " + . "only " . ($expl->{key_len} || 0) . " bytes " + . "of the " . ($expl->{key} || '?') . " index instead of " + . $tbl->{key_len} . ". See the --[no]check-plan documentation " + . "for more information.\n"); } return 0; # not safe } diff --git a/t/pt-table-checksum/chunk_index.t b/t/pt-table-checksum/chunk_index.t index be68f8d8..ab73d711 100644 --- a/t/pt-table-checksum/chunk_index.t +++ b/t/pt-table-checksum/chunk_index.t @@ -25,7 +25,7 @@ if ( !$dbh ) { plan skip_all => 'Cannot connect to sandbox master'; } else { - plan tests => 13; + plan tests => 14; } # The sandbox servers run with lock_wait_timeout=3 and it's not dynamic @@ -185,6 +185,22 @@ cmp_ok( "Skipped bad key_len chunks" ); +# Use --chunk-index:3 to use only the first 3 left-most columns of the index. +# Can't use bad_plan.t, however, because its row are almost all identical, +# so using 3 of 4 pk cols creates an infinite loop. +ok( + no_diff( + sub { + pt_table_checksum::main( + $master_dsn, '--max-load', '', + qw(--lock-wait-timeout 3 --chunk-size 5000 -t sakila.rental), + qw(--chunk-index rental_date:2 --explain --explain)); + }, + "t/pt-table-checksum/samples/n-chunk-index-cols.txt", + ), + "--chunk-index index:n" +); + # ############################################################################# # Done. # ############################################################################# diff --git a/t/pt-table-checksum/samples/bad-plan-bug-1010232.sql b/t/pt-table-checksum/samples/bad-plan-bug-1010232.sql new file mode 100644 index 00000000..981eb08e --- /dev/null +++ b/t/pt-table-checksum/samples/bad-plan-bug-1010232.sql @@ -0,0 +1,17 @@ +DROP DATABASE IF EXISTS bad_plan; +CREATE DATABASE bad_plan; +USE bad_plan; + +CREATE TABLE t ( + `c1` smallint(5) unsigned NOT NULL, + `c2` mediumint(8) unsigned NOT NULL DEFAULT '0', + `c3` smallint(5) unsigned NOT NULL DEFAULT '0', + `c4` smallint(5) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`c1`,`c2`,`c3`,`c4`) +) ENGINE=InnoDB; + +INSERT INTO t VALUES +(1,1,1,1),(1,1,1,2),(1,1,1,3),(1,1,1,4),(1,1,1,5),(1,1,1,6),(1,1,1,7),(1,1,1,8),(1,1,1,9),(1,1,1,10),(1,1,1,11),(1,1,1,12),(1,1,1,13),(1,1,1,14),(1,1,1,15),(1,1,1,16),(1,1,1,17),(1,1,1,18),(1,1,1,19),(1,1,1,20),(1,1,1,21),(1,1,1,22),(1,1,1,23),(1,1,1,24),(1,1,1,25),(1,1,1,26),(1,1,1,27),(1,1,1,28),(1,1,1,29),(1,1,1,30),(1,1,1,31),(1,1,1,32),(1,1,1,33),(1,1,1,34),(1,1,1,35),(1,1,1,36),(1,1,1,37),(1,1,1,38),(1,1,1,39),(1,1,1,40),(1,1,1,41),(1,1,1,42),(1,1,1,43),(1,1,1,44),(1,1,1,45),(1,1,1,46),(1,1,1,47),(1,1,1,48),(1,1,1,49),(1,1,1,50),(1,1,1,51),(1,1,1,52),(1,1,1,53),(1,1,1,54),(1,1,1,55),(1,1,1,56),(1,1,1,57),(1,1,1,58),(1,1,1,59),(1,1,1,60),(1,1,1,61),(1,1,1,62),(1,1,1,63),(1,1,1,64),(1,1,1,65),(1,1,1,66),(1,1,1,67),(1,1,1,68),(1,1,1,69),(1,1,1,70),(1,1,1,71),(1,1,1,72),(1,1,1,73),(1,1,1,74),(1,1,1,75),(1,1,1,76),(1,1,1,77),(1,1,1,78),(1,1,1,79),(1,1,1,80),(1,1,1,81),(1,1,1,82),(1,1,1,83),(1,1,1,84),(1,1,1,85),(1,1,1,86),(1,1,1,87),(1,1,1,88),(1,1,1,89),(1,1,1,90),(1,1,1,91),(1,1,1,92),(1,1,1,93),(1,1,1,94),(1,1,1,95),(1,1,1,96),(1,1,1,97),(1,1,1,98),(1,1,1,99),(1,1,1,100), +(1,1,2,1),(1,1,2,2),(1,1,2,3),(1,1,2,4),(1,1,2,5),(1,1,2,6),(1,1,2,7),(1,1,2,8),(1,1,2,9),(1,1,2,10),(1,1,2,11),(1,1,2,12),(1,1,2,13),(1,1,2,14),(1,1,2,15),(1,1,2,16),(1,1,2,17),(1,1,2,18),(1,1,2,19),(1,1,2,20),(1,1,2,21),(1,1,2,22),(1,1,2,23),(1,1,2,24),(1,1,2,25),(1,1,2,26),(1,1,2,27),(1,1,2,28),(1,1,2,29),(1,1,2,30),(1,1,2,31),(1,1,2,32),(1,1,2,33),(1,1,2,34),(1,1,2,35),(1,1,2,36),(1,1,2,37),(1,1,2,38),(1,1,2,39),(1,1,2,40),(1,1,2,41),(1,1,2,42),(1,1,2,43),(1,1,2,44),(1,1,2,45),(1,1,2,46),(1,1,2,47),(1,1,2,48),(1,1,2,49),(1,1,2,50),(1,1,2,51),(1,1,2,52),(1,1,2,53),(1,1,2,54),(1,1,2,55),(1,1,2,56),(1,1,2,57),(1,1,2,58),(1,1,2,59),(1,1,2,60),(1,1,2,61),(1,1,2,62),(1,1,2,63),(1,1,2,64),(1,1,2,65),(1,1,2,66),(1,1,2,67),(1,1,2,68),(1,1,2,69),(1,1,2,70),(1,1,2,71),(1,1,2,72),(1,1,2,73),(1,1,2,74),(1,1,2,75),(1,1,2,76),(1,1,2,77),(1,1,2,78),(1,1,2,79),(1,1,2,80),(1,1,2,81),(1,1,2,82),(1,1,2,83),(1,1,2,84),(1,1,2,85),(1,1,2,86),(1,1,2,87),(1,1,2,88),(1,1,2,89),(1,1,2,90),(1,1,2,91),(1,1,2,92),(1,1,2,93),(1,1,2,94),(1,1,2,95),(1,1,2,96),(1,1,2,97),(1,1,2,98),(1,1,2,99),(1,1,2,100); + +ANALYZE TABLE bad_plan.t; diff --git a/t/pt-table-checksum/samples/n-chunk-index-cols.txt b/t/pt-table-checksum/samples/n-chunk-index-cols.txt new file mode 100644 index 00000000..f08f80ea --- /dev/null +++ b/t/pt-table-checksum/samples/n-chunk-index-cols.txt @@ -0,0 +1,19 @@ +-- +-- sakila.rental +-- + +REPLACE INTO `percona`.`checksums` (db, tbl, chunk, chunk_index, lower_boundary, upper_boundary, this_cnt, this_crc) SELECT ?, ?, ?, ?, ?, ?, COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', `rental_id`, `rental_date`, `inventory_id`, `customer_id`, `return_date`, `staff_id`, `last_update` + 0, CONCAT(ISNULL(`return_date`)))) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `sakila`.`rental` FORCE INDEX(`rental_date`) WHERE ((`rental_date` > ?) OR (`rental_date` = ? AND `inventory_id` >= ?)) AND ((`rental_date` < ?) OR (`rental_date` = ? AND `inventory_id` <= ?)) /*checksum chunk*/ + +REPLACE INTO `percona`.`checksums` (db, tbl, chunk, chunk_index, lower_boundary, upper_boundary, this_cnt, this_crc) SELECT ?, ?, ?, ?, ?, ?, COUNT(*), '0' FROM `sakila`.`rental` FORCE INDEX(`rental_date`) WHERE ((`rental_date` < ?) OR (`rental_date` = ? AND `inventory_id` < ?)) ORDER BY `rental_date`, `inventory_id`, `customer_id` /*past lower chunk*/ + +REPLACE INTO `percona`.`checksums` (db, tbl, chunk, chunk_index, lower_boundary, upper_boundary, this_cnt, this_crc) SELECT ?, ?, ?, ?, ?, ?, COUNT(*), '0' FROM `sakila`.`rental` FORCE INDEX(`rental_date`) WHERE ((`rental_date` > ?) OR (`rental_date` = ? AND `inventory_id` > ?)) ORDER BY `rental_date`, `inventory_id`, `customer_id` /*past upper chunk*/ + +SELECT /*!40001 SQL_NO_CACHE */ `rental_date`, `rental_date`, `inventory_id` FROM `sakila`.`rental` FORCE INDEX(`rental_date`) WHERE ((`rental_date` > ?) OR (`rental_date` = ? AND `inventory_id` >= ?)) ORDER BY `rental_date`, `inventory_id`, `customer_id` LIMIT ?, 2 /*next chunk boundary*/ + +1 2005-05-24 22:53:30,2005-05-24 22:53:30,367 2005-07-09 01:17:08,2005-07-09 01:17:08,2388 +2 2005-07-09 01:19:03,2005-07-09 01:19:03,3438 2005-07-31 17:51:23,2005-07-31 17:51:23,2396 +3 2005-07-31 17:53:51,2005-07-31 17:53:51,928 2005-08-22 13:58:23,2005-08-22 13:58:23,2553 +4 2005-08-22 13:59:19,2005-08-22 13:59:19,3704 2006-02-14 15:16:03,2006-02-14 15:16:03,4568 +5 2005-05-24 22:53:30,2005-05-24 22:53:30,367 +6 2006-02-14 15:16:03,2006-02-14 15:16:03,4568 +