Skip to content

Commit 7f77041

Browse files
MDEV-37141 DML committed within XA transaction block after deadlock error and implicit rollback
Issue: When XA transaction is implicitly rolled back, we keep XA state XA_ACTIVE and set rm_error to ER_LOCK_DEADLOCK. Other than XA command we don't check for rm_error and DML and query are executed with a new transaction. Fix: One way to fix this issue is to set the XA state to XA_ROLLBACK_ONLY which is checked while opening table open_tables() and ER_XAER_RMFAIL is returned for any DML or Query.
1 parent 56ce9e7 commit 7f77041

File tree

5 files changed

+102
-8
lines changed

5 files changed

+102
-8
lines changed

mysql-test/main/xa.result

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,13 @@ connection con2;
135135
update t1 set c = 'aa' where a = 1;
136136
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
137137
select count(*) from t1;
138-
count(*)
139-
2
138+
ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the ROLLBACK ONLY state
140139
xa end 'a','c';
141-
ERROR XA102: XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected
140+
ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the ROLLBACK ONLY state
142141
xa rollback 'a','c';
142+
select count(*) from t1;
143+
count(*)
144+
2
143145
disconnect con2;
144146
connect con3,localhost,root,,;
145147
connection con3;
@@ -207,7 +209,7 @@ connection default;
207209
UPDATE t1 SET a=5 WHERE a=1;
208210
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
209211
XA END 'xid1';
210-
ERROR XA102: XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected
212+
ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the ROLLBACK ONLY state
211213
XA ROLLBACK 'xid1';
212214
XA START 'xid1';
213215
XA END 'xid1';

mysql-test/main/xa.test

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,12 @@ update t1 set c = 'bb' where a = 2;
165165
--sleep 1
166166
--error ER_LOCK_DEADLOCK
167167
update t1 set c = 'aa' where a = 1;
168+
--error ER_XAER_RMFAIL
168169
select count(*) from t1;
169-
--error ER_XA_RBDEADLOCK
170+
--error ER_XAER_RMFAIL
170171
xa end 'a','c';
171172
xa rollback 'a','c';
173+
select count(*) from t1;
172174
--disconnect con2
173175

174176
connect (con3,localhost,root,,);
@@ -274,7 +276,7 @@ WHERE ID=$conn_id AND STATE='Searching rows for update';
274276

275277
--error ER_LOCK_DEADLOCK
276278
UPDATE t1 SET a=5 WHERE a=1;
277-
--error ER_XA_RBDEADLOCK
279+
--error ER_XAER_RMFAIL
278280
XA END 'xid1';
279281
XA ROLLBACK 'xid1';
280282

mysql-test/suite/innodb/r/trx_deadlock.result

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,48 @@ SELECT @@in_transaction;
3535
@@in_transaction
3636
0
3737
ROLLBACK;
38-
disconnect con1;
3938
SELECT * FROM t1;
4039
col1 col2
4140
1 10
4241
2 100
4342
DROP TABLE t1;
43+
#
44+
# MDEV-37141 DML committed within XA transaction block after deadlock error and implicit rollback
45+
#
46+
CREATE TABLE t1(col1 INT PRIMARY KEY, col2 INT) ENGINE=InnoDB;
47+
INSERT INTO t1 VALUES (1, 1), (2, 2);
48+
SELECT * FROM t1;
49+
col1 col2
50+
1 1
51+
2 2
52+
connection con1;
53+
XA BEGIN 'x1';
54+
# XA Trx-1: Lock 1st record
55+
UPDATE t1 SET col2=10 where col1=1;
56+
connection default;
57+
XA BEGIN 'x2';
58+
# XA Trx-2: Lock 2nd record
59+
UPDATE t1 SET col2=100 where col1=2;
60+
connection con1;
61+
# XA Trx-1: Try locking 1st record : Wait
62+
UPDATE t1 SET col2=10 where col1=2;
63+
connection default;
64+
# Wait for XA Trx-1 to get into lock wait stage
65+
# XA Trx-2: Try locking 2nd record : Deadlock
66+
UPDATE t1 SET col2=100 where col1=1;
67+
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
68+
INSERT INTO t1 VALUES (3, 3), (4, 4);
69+
ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the ROLLBACK ONLY state
70+
XA END 'x2';
71+
ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the ROLLBACK ONLY state
72+
XA ROLLBACK 'x2';
73+
connection con1;
74+
XA END 'x1';
75+
XA ROLLBACK 'x1';
76+
connection default;
77+
SELECT * FROM t1;
78+
col1 col2
79+
1 1
80+
2 2
81+
DROP TABLE t1;
82+
disconnect con1;

mysql-test/suite/innodb/t/trx_deadlock.test

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
--echo # MDEV-36959 Deadlock does not rollback transaction fully
33
--echo #
44

5+
--source include/have_log_bin.inc
56
--source include/have_innodb.inc
67
--source include/count_sessions.inc
78

@@ -45,8 +46,55 @@ UPDATE t1 SET col2=100 where col1=2;
4546
SELECT @@in_transaction;
4647
ROLLBACK;
4748

48-
--disconnect con1
49+
SELECT * FROM t1;
50+
DROP TABLE t1;
51+
52+
--echo #
53+
--echo # MDEV-37141 DML committed within XA transaction block after deadlock error and implicit rollback
54+
--echo #
55+
56+
CREATE TABLE t1(col1 INT PRIMARY KEY, col2 INT) ENGINE=InnoDB;
57+
INSERT INTO t1 VALUES (1, 1), (2, 2);
58+
SELECT * FROM t1;
59+
60+
--connection con1
61+
XA BEGIN 'x1';
62+
--echo # XA Trx-1: Lock 1st record
63+
UPDATE t1 SET col2=10 where col1=1;
64+
65+
--connection default
66+
XA BEGIN 'x2';
67+
--echo # XA Trx-2: Lock 2nd record
68+
UPDATE t1 SET col2=100 where col1=2;
69+
70+
--connection con1
71+
--echo # XA Trx-1: Try locking 1st record : Wait
72+
--send UPDATE t1 SET col2=10 where col1=2
4973

74+
--connection default
75+
--echo # Wait for XA Trx-1 to get into lock wait stage
76+
let $wait_condition=
77+
SELECT COUNT(*) >= 2 FROM INFORMATION_SCHEMA.INNODB_LOCKS
78+
WHERE lock_table like "%t1%";
79+
--source include/wait_condition.inc
80+
81+
--echo # XA Trx-2: Try locking 2nd record : Deadlock
82+
--error ER_LOCK_DEADLOCK
83+
UPDATE t1 SET col2=100 where col1=1;
84+
--error ER_XAER_RMFAIL
85+
INSERT INTO t1 VALUES (3, 3), (4, 4);
86+
--error ER_XAER_RMFAIL
87+
XA END 'x2';
88+
XA ROLLBACK 'x2';
89+
90+
--connection con1
91+
--reap
92+
XA END 'x1';
93+
XA ROLLBACK 'x1';
94+
95+
--connection default
5096
SELECT * FROM t1;
5197
DROP TABLE t1;
98+
99+
--disconnect con1
52100
--source include/wait_until_count_sessions.inc

sql/sql_parse.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6248,6 +6248,9 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
62486248
one of storage engines (e.g. due to deadlock). Rollback transaction in
62496249
all storage engines including binary log.
62506250
*/
6251+
auto &xid_state= thd->transaction->xid_state;
6252+
if (xid_state.is_explicit_XA())
6253+
xid_state.set_rollback_only();
62516254
trans_rollback_implicit(thd);
62526255
thd->release_transactional_locks();
62536256
}

0 commit comments

Comments
 (0)