From b406f02f5bfac835c2c57800ef7cd753b6d2662a Mon Sep 17 00:00:00 2001 From: Daniel Nichter Date: Mon, 22 Oct 2012 15:30:29 -0600 Subject: [PATCH] Test and fix deadlock parsing with partition info. --- bin/pt-deadlock-logger | 2 +- t/pt-deadlock-logger/basics.t | 105 ++++++++++++------ .../samples/dead-lock-with-partitions.sql | 19 ++++ 3 files changed, 88 insertions(+), 38 deletions(-) create mode 100644 t/pt-deadlock-logger/samples/dead-lock-with-partitions.sql diff --git a/bin/pt-deadlock-logger b/bin/pt-deadlock-logger index 9613fffc..092fcac3 100755 --- a/bin/pt-deadlock-logger +++ b/bin/pt-deadlock-logger @@ -4072,7 +4072,7 @@ sub parse_deadlocks { $hash->{wait_hold} = $what eq 'WAITING FOR THIS LOCK TO BE GRANTED' ? 'w' : 'h'; @{$hash}{ qw(lock_type idx db tbl txn_id lock_mode) } = $body - =~ m{^(RECORD|TABLE) LOCKS? (?:space id \d+ page no \d+ n bits \d+ index `?$n`? of )?table `$n(?:/|`\.`)$n` trx id $t lock.mode (\S+)}m; + =~ m{^(RECORD|TABLE) LOCKS? (?:space id \d+ page no \d+ n bits \d+ index `?$n`? of )?table `$n(?:/|`\.`)$n`.*?trx id $t lock.mode (\S+)}m; if ( $hash->{txn_id} ) { my ( $high, $low ) = $hash->{txn_id} =~ m/^(\d+) (\d+)$/; $hash->{txn_id} = $high ? ( $low + ($high << 32) ) : $low; diff --git a/t/pt-deadlock-logger/basics.t b/t/pt-deadlock-logger/basics.t index ab2c4d66..0ff5a980 100644 --- a/t/pt-deadlock-logger/basics.t +++ b/t/pt-deadlock-logger/basics.t @@ -23,9 +23,6 @@ my $dbh2 = $sb->get_dbh_for('master', { PrintError => 0, RaiseError => 1, AutoCo if ( !$dbh1 || !$dbh2 ) { plan skip_all => 'Cannot connect to sandbox master'; } -else { - plan tests => 10; -} my $output; my $cnf = "/tmp/12345/my.sandbox.cnf"; @@ -44,46 +41,50 @@ $dbh2->commit; $dbh1->{InactiveDestroy} = 1; $dbh2->{InactiveDestroy} = 1; -# Fork off two children to deadlock against each other. -my %children; -foreach my $child ( 0..1 ) { - my $pid = fork(); - if ( defined($pid) && $pid == 0 ) { # I am a child - eval { - my $dbh = ($dbh1, $dbh2)[$child]; - my @stmts = ( - "set transaction isolation level serializable", - "begin", - "select * from test.dl where a = $child", - "update test.dl set a = $child where a <> $child", - ); - foreach my $stmt (@stmts[0..2]) { - $dbh->do($stmt); - } - sleep(1 + $child); - $dbh->do($stmts[-1]); - }; - if ( $EVAL_ERROR ) { - if ( $EVAL_ERROR !~ m/Deadlock found/ ) { - die $EVAL_ERROR; +sub make_deadlock { + # Fork off two children to deadlock against each other. + my %children; + foreach my $child ( 0..1 ) { + my $pid = fork(); + if ( defined($pid) && $pid == 0 ) { # I am a child + eval { + my $dbh = ($dbh1, $dbh2)[$child]; + my @stmts = ( + "set transaction isolation level serializable", + "begin", + "select * from test.dl where a = $child", + "update test.dl set a = $child where a <> $child", + ); + foreach my $stmt (@stmts[0..2]) { + $dbh->do($stmt); + } + sleep(1 + $child); + $dbh->do($stmts[-1]); + }; + if ( $EVAL_ERROR ) { + if ( $EVAL_ERROR !~ m/Deadlock found/ ) { + die $EVAL_ERROR; + } } + exit(0); } - exit(0); - } - elsif ( !defined($pid) ) { - die("Unable to fork for clearing deadlocks!\n"); + elsif ( !defined($pid) ) { + die("Unable to fork for clearing deadlocks!\n"); + } + + # I already exited if I'm a child, so I'm the parent. + $children{$child} = $pid; } - # I already exited if I'm a child, so I'm the parent. - $children{$child} = $pid; + # Wait for the children to exit. + foreach my $child ( keys %children ) { + my $pid = waitpid($children{$child}, 0); + } + $dbh1->commit; + $dbh2->commit; } -# Wait for the children to exit. -foreach my $child ( keys %children ) { - my $pid = waitpid($children{$child}, 0); -} -$dbh1->commit; -$dbh2->commit; +make_deadlock(); # Test that there is a deadlock $output = $dbh1->selectrow_hashref('show /*!40101 engine*/ innodb status')->{status}; @@ -162,6 +163,35 @@ ok( 'Deadlocks recorded in table again' ); +# ############################################################################# +# Bug 1043528: pt-deadlock-logger can't parse db/tbl/index on partitioned tables +# ############################################################################# +SKIP: { + skip "Deadlock with partitions test requires MySQL 5.1 and newer", 1 + unless $sandbox_version ge '5.1'; + + $dbh1->do('rollback'); + $dbh2->do('rollback'); + $output = 'foo'; + $dbh1->do('TRUNCATE TABLE test.deadlocks'); + + $sb->load_file('master', "t/pt-deadlock-logger/samples/dead-lock-with-partitions.sql"); + + make_deadlock(); + + $output = output( + sub { pt_deadlock_logger::main("F=/tmp/12345/my.sandbox.cnf", + qw(--print) ); + } + ); + + like( + $output, + qr/test dl PRIMARY RECORD/, + "Deadlock with partitions (bug 1043528)" + ); +} + # ############################################################################# # Done. # ############################################################################# @@ -169,4 +199,5 @@ $dbh1->commit; $dbh2->commit; $sb->wipe_clean($dbh1); ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); +done_testing; exit; diff --git a/t/pt-deadlock-logger/samples/dead-lock-with-partitions.sql b/t/pt-deadlock-logger/samples/dead-lock-with-partitions.sql new file mode 100644 index 00000000..e8a957d3 --- /dev/null +++ b/t/pt-deadlock-logger/samples/dead-lock-with-partitions.sql @@ -0,0 +1,19 @@ +drop database if exists test; +create database test; +use test; + +CREATE TABLE dl ( + id INT NOT NULL, + store_id INT NOT NULL, + a INT NOT NULL, + primary key (id, store_id), + unique key (store_id) +) ENGINE=InnoDB + +PARTITION BY RANGE (store_id) ( + PARTITION p0 VALUES LESS THAN (6), + PARTITION p1 VALUES LESS THAN (11) +); + +insert into test.dl values + (1, 1, 0), (2, 2, 0), (3, 3, 0), (4, 4, 1), (5, 5, 1), (6, 6, 1);