summaryrefslogtreecommitdiff
path: root/mysql-test/suite/innodb/t/deadlock_in_subqueries_join.test
blob: b3adfb3b02d7952b83628c1466f05ea9e1983dcf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
--source include/have_innodb.inc
--source include/count_sessions.inc

CREATE TABLE t1 (
  pkey int NOT NULL PRIMARY KEY,
  c int
) ENGINE=InnoDB;

INSERT INTO t1 VALUES(1,1);

CREATE TABLE t2 (
  pkey int NOT NULL PRIMARY KEY,
  c int
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO t2 VALUES (2, NULL);

# The following table is to increase tansaction weight on deadlock resolution
CREATE TABLE t3 (c int) engine = InnoDB;
INSERT INTO t3 VALUES (10), (20), (30), (40), (50);

--let $i= 2
--let $delete= 2
--let $update= 1
--connect(con1, localhost,root,,)

while($i) {
--connection default
START TRANSACTION; # trx 1
# The following update is necessary to increase the transaction weight, which is
# calculated as the number of locks + the number of undo records during deadlock
# report. Victim's transaction should have minimum weight. We need trx 2 to be
# choosen as victim, that's why we need to increase the current transaction
# weight.
UPDATE t3 SET c=c+1000;
SELECT * FROM t1 FOR UPDATE;

--connection con1
START TRANSACTION; # trx 2
# 1) read record from t2, lock it
# 2) check if the read record should be deleted, i.e. read record from t1,
# as the record from t1 is locked by trx 1, the subselect will be suspended.
# see 'while' loop in mysql_delete() or mysql_update() and
# select->skip_record(thd) call for details.
if ($i == $delete) {
--send DELETE FROM t2 WHERE c NOT IN (SELECT ref_0.pkey FROM t1 AS ref_0 INNER JOIN t1 AS ref_1 ON ref_0.c = ref_0.pkey)
}
if ($i == $update) {
--send UPDATE t2 SET pkey=pkey+10 WHERE c NOT IN (SELECT ref_0.pkey FROM t1 AS ref_0 INNER JOIN t1 AS ref_1 ON ref_0.c = ref_0.pkey)
}

--connection default
let $wait_condition=
  SELECT count(*) = 1 FROM information_schema.processlist
  WHERE (state = 'Sending data' OR state = "Updating")
  AND (info LIKE 'delete from t2 where%' OR
       info LIKE 'UPDATE t2 SET pkey=pkey+10 WHERE%');
--source include/wait_condition.inc

# The record from t2 is locked by the previous delete, so trx 2 is waiting for
# trx 1, and trx 1 will be blocked by trx 2 with the following SELECT. So we
# have deadlock here. And trx 2 is chosen as deadlock victim as trx 1 has
# greater weight.
SELECT * FROM t2 FOR UPDATE;
COMMIT;

--connection con1
# If the bug is not fixed, there will be assertion failure as
# mysql_delete()/mysql_update() will continue execution despite its subselect
# got deadlock error
--error ER_LOCK_DEADLOCK
--reap
COMMIT;
--dec $i
}

--disconnect con1

--connection default
DROP TABLE t1,t2,t3;
--source include/wait_until_count_sessions.inc