1--source include/have_innodb.inc 2--source include/have_debug_sync.inc 3 4--echo # 5--echo #Bug#11759688 52020: InnoDB can still deadlock 6--echo #on just INSERT...ON DUPLICATE KEY 7--echo #a.k.a. Bug#7975 deadlock without any locking, simple select and update 8--echo # 9 10CREATE TABLE t1 (a INT PRIMARY KEY, b INT NOT NULL) ENGINE=InnoDB; 11 12INSERT INTO t1 VALUES(3,1); 13 14connect (con1,localhost,root,,); 15connect (con2,localhost,root,,); 16connection con1; 17 18BEGIN; 19# normal INSERT of a duplicate should only S-lock the existing record (3,1) 20SET DEBUG_SYNC='write_row_noreplace SIGNAL insert1 WAIT_FOR select1'; 21--send 22INSERT INTO t1 VALUES(3,2); 23 24connection default; 25SET DEBUG_SYNC='now WAIT_FOR insert1'; 26# this should S-lock (3,1); no conflict 27SELECT * FROM t1 LOCK IN SHARE MODE; 28# this should X-lock (3,1), conflicting with con1 29--send 30SELECT * FROM t1 FOR UPDATE; 31 32connection con2; 33# Check that the above SELECT is blocked 34let $wait_condition= 35 select count(*) = 1 from information_schema.processlist 36 where state = 'Sending data' and 37 info = 'SELECT * FROM t1 FOR UPDATE'; 38--source include/wait_condition.inc 39SET DEBUG_SYNC='now SIGNAL select1'; 40 41connection con1; 42--error ER_DUP_ENTRY 43reap; 44# We are still holding an S-lock on (3,1) after the failed INSERT. 45# The following will upgrade it to an X-lock, causing a deadlock. 46# InnoDB should resolve the deadlock by aborting the blocked SELECT. 47INSERT INTO t1 VALUES(3,3) ON DUPLICATE KEY UPDATE b=b+10; 48 49connection default; 50--error ER_LOCK_DEADLOCK 51reap; 52connection con1; 53COMMIT; 54 55SET DEBUG_SYNC='write_row_replace SIGNAL insert2 WAIT_FOR select2'; 56--send 57REPLACE INTO t1 VALUES(3,4); 58 59connection default; 60SET DEBUG_SYNC='now WAIT_FOR insert2'; 61SELECT * FROM t1; 62--send 63SELECT * FROM t1 LOCK IN SHARE MODE; 64 65connection con2; 66# Check that the above SELECT is blocked because of X lock. 67let $wait_condition= 68 select count(*) = 1 from information_schema.processlist 69 where state = 'Sending data' and 70 info = 'SELECT * FROM t1 LOCK IN SHARE MODE'; 71--source include/wait_condition.inc 72SET DEBUG_SYNC='now SIGNAL select2'; 73 74connection con1; 75reap; 76 77connection default; 78reap; 79 80connection con1; 81SET DEBUG_SYNC='write_row_replace SIGNAL insert3 WAIT_FOR select3'; 82--send 83INSERT INTO t1 VALUES(3,5) ON DUPLICATE KEY UPDATE b=b+20; 84 85connection default; 86SET DEBUG_SYNC='now WAIT_FOR insert3'; 87--send 88SELECT b FROM t1 LOCK IN SHARE MODE; 89 90connection con2; 91# Check that the above SELECT is blocked because of X lock. 92let $wait_condition= 93 select count(*) = 1 from information_schema.processlist 94 where state = 'Sending data' and 95 info = 'SELECT b FROM t1 LOCK IN SHARE MODE'; 96--source include/wait_condition.inc 97SET DEBUG_SYNC='now SIGNAL select3'; 98 99connection default; 100reap; 101 102connection con1; 103reap; 104SET DEBUG_SYNC='write_row_noreplace SIGNAL insert4 WAIT_FOR select4'; 105--send 106LOAD DATA INFILE '../../std_data/loaddata5.dat' INTO TABLE t1 FIELDS TERMINATED BY '' ENCLOSED BY '' (a, b); 107 108connection default; 109SET DEBUG_SYNC='now WAIT_FOR insert4'; 110# this should S-lock (3,1); no conflict 111SELECT b FROM t1 WHERE a=3 LOCK IN SHARE MODE; 112# this should X-lock (3,1), conflicting with con1 113--send 114SELECT b FROM t1 WHERE a=3 FOR UPDATE; 115 116connection con2; 117# Check that the above SELECT is blocked 118let $wait_condition= 119 select count(*) = 1 from information_schema.processlist 120 where state = 'statistics' and 121 info = 'SELECT b FROM t1 WHERE a=3 FOR UPDATE'; 122--source include/wait_condition.inc 123SET DEBUG_SYNC='now SIGNAL select4'; 124 125connection default; 126reap; 127 128connection con1; 129--error ER_DUP_ENTRY 130reap; 131SET DEBUG_SYNC='write_row_noreplace SIGNAL insert5 WAIT_FOR select5'; 132--send 133LOAD DATA INFILE '../../std_data/loaddata5.dat' IGNORE INTO TABLE t1 FIELDS TERMINATED BY '' ENCLOSED BY '' (a, b); 134 135connection default; 136SET DEBUG_SYNC='now WAIT_FOR insert5'; 137SELECT * FROM t1; 138# this should S-lock; no conflict 139SELECT * FROM t1 WHERE a=3 LOCK IN SHARE MODE; 140# this should X-lock, conflicting with the S-lock of the IGNORE in con1 141--send 142SELECT * FROM t1 WHERE a=3 FOR UPDATE; 143 144connection con2; 145# Check that the above SELECT is blocked 146let $wait_condition= 147 select count(*) = 1 from information_schema.processlist 148 where state = 'statistics' and 149 info = 'SELECT * FROM t1 WHERE a=3 FOR UPDATE'; 150--source include/wait_condition.inc 151SET DEBUG_SYNC='now SIGNAL select5'; 152 153connection con1; 154reap; 155connection default; 156reap; 157 158connection con1; 159SET DEBUG_SYNC='write_row_replace SIGNAL insert6 WAIT_FOR select6'; 160--send 161LOAD DATA INFILE '../../std_data/loaddata5.dat' REPLACE INTO TABLE t1 FIELDS TERMINATED BY '' ENCLOSED BY '' (a, b); 162 163connection default; 164SET DEBUG_SYNC='now WAIT_FOR insert6'; 165SELECT * FROM t1; 166# this should conflict with the X-lock acquired by the REPLACE 167--send 168SELECT a,b FROM t1 LOCK IN SHARE MODE; 169 170connection con2; 171# Check that the above SELECT is blocked 172let $wait_condition= 173 select count(*) = 1 from information_schema.processlist 174 where state = 'Sending data' and 175 info = 'SELECT a,b FROM t1 LOCK IN SHARE MODE'; 176--source include/wait_condition.inc 177SET DEBUG_SYNC='now SIGNAL select6'; 178 179connection con1; 180reap; 181connection default; 182reap; 183 184disconnect con1; 185disconnect con2; 186 187connection default; 188SET DEBUG_SYNC='RESET'; 189DROP TABLE t1; 190 191# Test case for TEMPORARY TABLE, with several unique indexes 192START TRANSACTION; 193 194CREATE TEMPORARY TABLE t1 (a INT, b CHAR(10), d VARCHAR(100), c INT, UNIQUE INDEX(a), UNIQUE INDEX(b), UNIQUE INDEX(d)) ENGINE = InnoDB; 195 196INSERT INTO t1 VALUES(2, 'abcde', 'qwerty', 200); 197 198REPLACE INTO t1 VALUES(2, 'QWERTY', 'ZXCVBB', 300); 199 200SELECT * FROM t1; 201 202COMMIT; 203 204DROP TABLE t1; 205