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