Commit 83a19306 authored by Alexey Botchkov's avatar Alexey Botchkov

MDEV-7974 XA transactions.

FLUSH TABLES WITH READ LOCK now blocks the XA COMMIT/ROLLBACK/PREPARE
statements as they write to the binlog/Innodb redo.
parent dfa24e55
...@@ -162,7 +162,19 @@ Success: FTWRL is blocked when 'alter event e1 comment 'test'' is active in anot ...@@ -162,7 +162,19 @@ Success: FTWRL is blocked when 'alter event e1 comment 'test'' is active in anot
# --read-only for a discussion why. # --read-only for a discussion why.
# #
Success: Was able to run 'analyze table t1_base' under FTWRL. Success: Was able to run 'analyze table t1_base' under FTWRL.
Success: Was able to run 'analyze table t1_base' with FTWRL active in another connection. Timeout in wait_condition.inc for select count(*) = 0 from information_schema.processlist
where info = "analyze table t1_base"
Id User Host db Command Time State Info Progress
3 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
4 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
1 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
2 system user NULL Daemon NULL InnoDB purge coordinator NULL 0.000
5 system user NULL Daemon NULL InnoDB shutdown handler NULL 0.000
9 root localhost test Query 31 Waiting for backup lock analyze table t1_base 0.000
10 root localhost test Query 0 Init show full processlist 0.000
11 root localhost test Sleep 31 NULL 0.000
12 root localhost test Sleep 31 NULL 0.000
Error: Wasn't able to run 'analyze table t1_base' with FTWRL active in another connection!
Success: Was able to run FTWRL while 'analyze table t1_base' was active in another connection. Success: Was able to run FTWRL while 'analyze table t1_base' was active in another connection.
# #
# 3) BEGIN, ROLLBACK and COMMIT statements. # 3) BEGIN, ROLLBACK and COMMIT statements.
...@@ -1309,6 +1321,8 @@ unlock tables; ...@@ -1309,6 +1321,8 @@ unlock tables;
# Check that XA non-COMMIT statements are not and COMMIT is # Check that XA non-COMMIT statements are not and COMMIT is
# blocked by active FTWRL in another connection # blocked by active FTWRL in another connection
# #
# XA COMMIT, XA ROLLBACK and XA PREPARE does take COMMIT lock to ensure
# that nothing is written to bin log and redo log under FTWRL mode.
connection con1; connection con1;
flush tables with read lock; flush tables with read lock;
connection default; connection default;
...@@ -1321,11 +1335,51 @@ connection con1; ...@@ -1321,11 +1335,51 @@ connection con1;
flush tables with read lock; flush tables with read lock;
connection default; connection default;
xa end 'test1'; xa end 'test1';
xa prepare 'test1'; xa prepare 'test1';;
xa rollback 'test1'; connection con1;
Timeout in wait_condition.inc for select count(*) = 1 from information_schema.processlist
where state = "Waiting for commit lock" and
info = "xa prepare 'test1'"
Id User Host db Command Time State Info Progress
3 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
4 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
1 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
2 system user NULL Daemon NULL InnoDB purge coordinator NULL 0.000
5 system user NULL Daemon NULL InnoDB shutdown handler NULL 0.000
9 root localhost test Query 30 Waiting for backup lock xa prepare 'test1' 0.000
10 root localhost test Query 0 Init show full processlist 0.000
11 root localhost test Sleep 30 NULL 0.000
12 root localhost test Sleep 63 NULL 0.000
unlock tables;
# Switching to connection 'default'.
connection default;
# Reap XA PREPARE.
# Switching to connection 'con1'.
connection con1; connection con1;
flush tables with read lock;
# Switching to connection 'default'.
connection default;
# Send XA ROLLBACK 'test1'
xa rollback 'test1';
# Switching to connection 'con1'.
connection con1;
# Wait until XA ROLLBACK is blocked.
Timeout in wait_condition.inc for select count(*) = 1 from information_schema.processlist
where state = "Waiting for commit lock" and
info = "xa rollback 'test1'"
Id User Host db Command Time State Info Progress
3 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
4 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
1 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
2 system user NULL Daemon NULL InnoDB purge coordinator NULL 0.000
5 system user NULL Daemon NULL InnoDB shutdown handler NULL 0.000
9 root localhost test Query 30 Waiting for backup lock xa rollback 'test1' 0.000
10 root localhost test Query 0 Init show full processlist 0.000
11 root localhost test Sleep 61 NULL 0.000
12 root localhost test Sleep 94 NULL 0.000
unlock tables; unlock tables;
connection default; connection default;
# Reap XA ROLLBACK
xa start 'test1'; xa start 'test1';
insert into t3_trans values (1); insert into t3_trans values (1);
connection con1; connection con1;
...@@ -1333,7 +1387,33 @@ flush tables with read lock; ...@@ -1333,7 +1387,33 @@ flush tables with read lock;
connection default; connection default;
connection default; connection default;
xa end 'test1'; xa end 'test1';
# Send XA PREPARE 'test1'
xa prepare 'test1'; xa prepare 'test1';
# Switching to connection 'con1'.
connection con1;
# Wait until XA PREPARE is blocked.
Timeout in wait_condition.inc for select count(*) = 1 from information_schema.processlist
where state = "Waiting for commit lock" and
info = "xa prepare 'test1'"
Id User Host db Command Time State Info Progress
3 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
4 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
1 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
2 system user NULL Daemon NULL InnoDB purge coordinator NULL 0.000
5 system user NULL Daemon NULL InnoDB shutdown handler NULL 0.000
9 root localhost test Query 31 Waiting for backup lock xa prepare 'test1' 0.000
10 root localhost test Query 0 Init show full processlist 0.000
11 root localhost test Sleep 92 NULL 0.000
12 root localhost test Sleep 125 NULL 0.000
unlock tables;
# Switching to connection 'default'.
connection default;
# Reap XA PREPARE.
# Switching to connection 'con1'.
connection con1;
flush tables with read lock;
# Switching to connection 'default'.
connection default;
# Send: # Send:
xa commit 'test1';; xa commit 'test1';;
connection con1; connection con1;
...@@ -1343,6 +1423,77 @@ connection default; ...@@ -1343,6 +1423,77 @@ connection default;
# Reap XA COMMIT. # Reap XA COMMIT.
delete from t3_trans; delete from t3_trans;
# #
# Check that XA COMMIT / ROLLBACK for prepared transaction from a
# disconnected session is blocked by active FTWRL in another connection.
#
# Create temporary connection for XA transaction.
connect con_tmp,localhost,root,,;
xa start 'test1';
insert into t3_trans values (1);
xa end 'test1';
xa prepare 'test1';
# Disconnect temporary connection
disconnect con_tmp;
# Create temporary connection for XA transaction.
connect con_tmp,localhost,root,,;
xa start 'test2';
insert into t3_trans values (2);
xa end 'test2';
xa prepare 'test2';
# Disconnect temporary connection
disconnect con_tmp;
# Switching to connection 'con1'.
connection con1;
flush tables with read lock;
# Switching to connection 'default'.
connection default;
# Send XA ROLLBACK 'test1'
xa rollback 'test1';
# Switching to connection 'con1'.
connection con1;
# Wait until XA ROLLBACK is blocked.
Timeout in wait_condition.inc for select count(*) = 1 from information_schema.processlist
where state = "Waiting for commit lock" and
info = "xa rollback 'test1'"
Id User Host db Command Time State Info Progress
3 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
4 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
1 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
2 system user NULL Daemon NULL InnoDB purge coordinator NULL 0.000
5 system user NULL Daemon NULL InnoDB shutdown handler NULL 0.000
9 root localhost test Query 30 Waiting for backup lock xa rollback 'test1' 0.000
10 root localhost test Query 0 Init show full processlist 0.000
11 root localhost test Sleep 123 NULL 0.000
12 root localhost test Sleep 157 NULL 0.000
unlock tables;
flush tables with read lock;
# Switching to connection 'default'.
connection default;
# Reap XA ROLLBACK
# Send XA COMMIT
xa commit 'test2';;
# Switching to connection 'con1'.
connection con1;
# Wait until XA COMMIT is blocked.
Timeout in wait_condition.inc for select count(*) = 1 from information_schema.processlist
where state = "Waiting for commit lock" and
info = "xa commit 'test2'"
Id User Host db Command Time State Info Progress
3 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
4 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
1 system user NULL Daemon NULL InnoDB purge worker NULL 0.000
2 system user NULL Daemon NULL InnoDB purge coordinator NULL 0.000
5 system user NULL Daemon NULL InnoDB shutdown handler NULL 0.000
9 root localhost test Query 31 Waiting for backup lock xa commit 'test2' 0.000
10 root localhost test Query 0 Init show full processlist 0.000
11 root localhost test Sleep 154 NULL 0.000
12 root localhost test Sleep 188 NULL 0.000
unlock tables;
# Switching to connection 'default'.
connection default;
# Reap XA COMMIT.
delete from t3_trans;
#
# Check that XA COMMIT blocks FTWRL in another connection. # Check that XA COMMIT blocks FTWRL in another connection.
xa start 'test1'; xa start 'test1';
insert into t3_trans values (1); insert into t3_trans values (1);
...@@ -1412,6 +1563,7 @@ flush tables with read lock; ...@@ -1412,6 +1563,7 @@ flush tables with read lock;
# Implicit commits are allowed under FTWRL. # Implicit commits are allowed under FTWRL.
analyze table t3_trans; analyze table t3_trans;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t3_trans analyze status Engine-independent statistics collected
test.t3_trans analyze status OK test.t3_trans analyze status OK
unlock tables; unlock tables;
# #
...@@ -1425,6 +1577,7 @@ unlock tables; ...@@ -1425,6 +1577,7 @@ unlock tables;
connection default; connection default;
# Reap ANALYZE TABLE # Reap ANALYZE TABLE
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t3_trans analyze status Engine-independent statistics collected
test.t3_trans analyze status OK test.t3_trans analyze status OK
# #
# 39.1.b) CHECK TABLE for transactional table is compatible with FTWRL. # 39.1.b) CHECK TABLE for transactional table is compatible with FTWRL.
......
...@@ -1590,6 +1590,8 @@ unlock tables; ...@@ -1590,6 +1590,8 @@ unlock tables;
--echo # Check that XA non-COMMIT statements are not and COMMIT is --echo # Check that XA non-COMMIT statements are not and COMMIT is
--echo # blocked by active FTWRL in another connection --echo # blocked by active FTWRL in another connection
--echo # --echo #
--echo # XA COMMIT, XA ROLLBACK and XA PREPARE does take COMMIT lock to ensure
--echo # that nothing is written to bin log and redo log under FTWRL mode.
connection $con_aux1; connection $con_aux1;
flush tables with read lock; flush tables with read lock;
connection default; connection default;
...@@ -1602,11 +1604,37 @@ connection $con_aux1; ...@@ -1602,11 +1604,37 @@ connection $con_aux1;
flush tables with read lock; flush tables with read lock;
connection default; connection default;
xa end 'test1'; xa end 'test1';
xa prepare 'test1'; --send xa prepare 'test1';
xa rollback 'test1';
connection $con_aux1; connection $con_aux1;
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Waiting for commit lock" and
info = "xa prepare 'test1'";
--source include/wait_condition.inc
unlock tables;
--echo # Switching to connection 'default'.
connection default;
--echo # Reap XA PREPARE.
--reap
--echo # Switching to connection '$con_aux1'.
connection $con_aux1;
flush tables with read lock;
--echo # Switching to connection 'default'.
connection default;
--echo # Send XA ROLLBACK 'test1'
--send xa rollback 'test1'
--echo # Switching to connection '$con_aux1'.
connection $con_aux1;
--echo # Wait until XA ROLLBACK is blocked.
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Waiting for commit lock" and
info = "xa rollback 'test1'";
--source include/wait_condition.inc
unlock tables; unlock tables;
connection default; connection default;
--echo # Reap XA ROLLBACK
--reap
xa start 'test1'; xa start 'test1';
insert into t3_trans values (1); insert into t3_trans values (1);
connection $con_aux1; connection $con_aux1;
...@@ -1614,7 +1642,27 @@ flush tables with read lock; ...@@ -1614,7 +1642,27 @@ flush tables with read lock;
connection default; connection default;
connection default; connection default;
xa end 'test1'; xa end 'test1';
xa prepare 'test1'; --echo # Send XA PREPARE 'test1'
--send xa prepare 'test1'
--echo # Switching to connection '$con_aux1'.
connection $con_aux1;
--echo # Wait until XA PREPARE is blocked.
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Waiting for commit lock" and
info = "xa prepare 'test1'";
--source include/wait_condition.inc
unlock tables;
--echo # Switching to connection 'default'.
connection default;
--echo # Reap XA PREPARE.
--reap
--echo # Switching to connection '$con_aux1'.
connection $con_aux1;
flush tables with read lock;
--echo # Switching to connection 'default'.
connection default;
--echo # Send: --echo # Send:
--send xa commit 'test1'; --send xa commit 'test1';
connection $con_aux1; connection $con_aux1;
...@@ -1629,6 +1677,64 @@ connection default; ...@@ -1629,6 +1677,64 @@ connection default;
--echo # Reap XA COMMIT. --echo # Reap XA COMMIT.
--reap --reap
delete from t3_trans; delete from t3_trans;
--echo #
--echo # Check that XA COMMIT / ROLLBACK for prepared transaction from a
--echo # disconnected session is blocked by active FTWRL in another connection.
--echo #
--echo # Create temporary connection for XA transaction.
connect (con_tmp,localhost,root,,);
xa start 'test1';
insert into t3_trans values (1);
xa end 'test1';
xa prepare 'test1';
--echo # Disconnect temporary connection
disconnect con_tmp;
--echo # Create temporary connection for XA transaction.
connect (con_tmp,localhost,root,,);
xa start 'test2';
insert into t3_trans values (2);
xa end 'test2';
xa prepare 'test2';
--echo # Disconnect temporary connection
disconnect con_tmp;
--echo # Switching to connection '$con_aux1'.
connection $con_aux1;
flush tables with read lock;
--echo # Switching to connection 'default'.
connection default;
--echo # Send XA ROLLBACK 'test1'
--send xa rollback 'test1'
--echo # Switching to connection '$con_aux1'.
connection $con_aux1;
--echo # Wait until XA ROLLBACK is blocked.
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Waiting for commit lock" and
info = "xa rollback 'test1'";
--source include/wait_condition.inc
unlock tables;
flush tables with read lock;
--echo # Switching to connection 'default'.
connection default;
--echo # Reap XA ROLLBACK
--reap
--echo # Send XA COMMIT
--send xa commit 'test2';
--echo # Switching to connection '$con_aux1'.
connection $con_aux1;
--echo # Wait until XA COMMIT is blocked.
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Waiting for commit lock" and
info = "xa commit 'test2'";
--source include/wait_condition.inc
unlock tables;
--echo # Switching to connection 'default'.
connection default;
--echo # Reap XA COMMIT.
--reap
delete from t3_trans;
--echo # --echo #
--echo # Check that XA COMMIT blocks FTWRL in another connection. --echo # Check that XA COMMIT blocks FTWRL in another connection.
xa start 'test1'; xa start 'test1';
......
...@@ -355,3 +355,63 @@ DROP TABLE t1, t2, t3; ...@@ -355,3 +355,63 @@ DROP TABLE t1, t2, t3;
xa rollback 'testb',0x2030405060,11; xa rollback 'testb',0x2030405060,11;
XA RECOVER; XA RECOVER;
formatID gtrid_length bqual_length data formatID gtrid_length bqual_length data
# Check XA state when lock_wait_timeout happens
# More tests added to flush_read_lock.test
connect con_tmp,localhost,root,,;
set session lock_wait_timeout=1;
create table asd (a int);
xa start 'test1';
insert into asd values(1);
xa end 'test1';
connection default;
flush table with read lock;
connection con_tmp;
# PREPARE error will do auto rollback.
xa prepare 'test1';
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
show errors;
Level Code Message
Error 1205 Lock wait timeout exceeded; try restarting transaction
Error 1402 XA_RBROLLBACK: Transaction branch was rolled back
connection default;
unlock tables;
connection con_tmp;
xa start 'test1';
insert into asd values(1);
xa end 'test1';
xa prepare 'test1';
connection default;
flush tables with read lock;
connection con_tmp;
# LOCK error during ROLLBACK will not alter transaction state.
xa rollback 'test1';
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
show errors;
Level Code Message
Error 1205 Lock wait timeout exceeded; try restarting transaction
Error 1401 XAER_RMERR: Fatal error occurred in the transaction branch - check your data for consistency
xa recover;
formatID gtrid_length bqual_length data
1 5 0 test1
# LOCK error during COMMIT will not alter transaction state.
xa commit 'test1';
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
show errors;
Level Code Message
Error 1205 Lock wait timeout exceeded; try restarting transaction
Error 1401 XAER_RMERR: Fatal error occurred in the transaction branch - check your data for consistency
xa recover;
formatID gtrid_length bqual_length data
1 5 0 test1
connection default;
unlock tables;
connection con_tmp;
xa rollback 'test1';
Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back
Warning 1196 Some non-transactional changed tables couldn't be rolled back
xa recover;
formatID gtrid_length bqual_length data
drop table asd;
disconnect con_tmp;
connection default;
...@@ -468,7 +468,6 @@ REPLACE INTO t2 SELECT * FROM t2; ...@@ -468,7 +468,6 @@ REPLACE INTO t2 SELECT * FROM t2;
INSERT INTO t3 VALUES (1); INSERT INTO t3 VALUES (1);
XA BEGIN 'xid3'; XA BEGIN 'xid3';
#Cleanup #Cleanup
--disconnect con2 --disconnect con2
--connection default --connection default
...@@ -481,3 +480,48 @@ XA RECOVER; ...@@ -481,3 +480,48 @@ XA RECOVER;
--source include/wait_until_count_sessions.inc --source include/wait_until_count_sessions.inc
--echo # Check XA state when lock_wait_timeout happens
--echo # More tests added to flush_read_lock.test
connect (con_tmp,localhost,root,,);
set session lock_wait_timeout=1;
create table asd (a int);
xa start 'test1';
insert into asd values(1);
xa end 'test1';
connection default;
flush table with read lock;
connection con_tmp;
--echo # PREPARE error will do auto rollback.
--ERROR ER_LOCK_WAIT_TIMEOUT
xa prepare 'test1';
show errors;
connection default;
unlock tables;
connection con_tmp;
xa start 'test1';
insert into asd values(1);
xa end 'test1';
xa prepare 'test1';
connection default;
flush tables with read lock;
connection con_tmp;
--echo # LOCK error during ROLLBACK will not alter transaction state.
--ERROR ER_LOCK_WAIT_TIMEOUT
xa rollback 'test1';
show errors;
xa recover;
--echo # LOCK error during COMMIT will not alter transaction state.
--ERROR ER_LOCK_WAIT_TIMEOUT
xa commit 'test1';
show errors;
xa recover;
connection default;
unlock tables;
connection con_tmp;
xa rollback 'test1';
xa recover;
drop table asd;
disconnect con_tmp;
--source include/wait_until_disconnected.inc
connection default;
...@@ -1047,18 +1047,39 @@ bool trans_xa_prepare(THD *thd) ...@@ -1047,18 +1047,39 @@ bool trans_xa_prepare(THD *thd)
xa_state_names[thd->transaction.xid_state.xa_state]); xa_state_names[thd->transaction.xid_state.xa_state]);
else if (!thd->transaction.xid_state.xid.eq(thd->lex->xid)) else if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
my_error(ER_XAER_NOTA, MYF(0)); my_error(ER_XAER_NOTA, MYF(0));
else if (ha_prepare(thd))
{
xid_cache_delete(thd, &thd->transaction.xid_state);
thd->transaction.xid_state.xa_state= XA_NOTR;
my_error(ER_XA_RBROLLBACK, MYF(0));
}
else else
{ {
res= 0; /*
thd->transaction.xid_state.xa_state= XA_PREPARED; Acquire metadata lock which will ensure that COMMIT is blocked
if (thd->variables.pseudo_slave_mode) by active FLUSH TABLES WITH READ LOCK (and vice versa COMMIT in
res= applier_reset_xa_trans(thd); progress blocks FTWRL).
We allow FLUSHer to COMMIT; we assume FLUSHer knows what it does.
*/
MDL_request mdl_request;
mdl_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_COMMIT,
MDL_STATEMENT);
if (thd->mdl_context.acquire_lock(&mdl_request,
thd->variables.lock_wait_timeout) ||
ha_prepare(thd))
{
if (!mdl_request.ticket)
ha_rollback_trans(thd, TRUE);
thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
thd->transaction.all.reset();
thd->server_status&=
~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY);
xid_cache_delete(thd, &thd->transaction.xid_state);
thd->transaction.xid_state.xa_state= XA_NOTR;
my_error(ER_XA_RBROLLBACK, MYF(0));
}
else
{
res= 0;
thd->transaction.xid_state.xa_state= XA_PREPARED;
if (thd->variables.pseudo_slave_mode)
res= applier_reset_xa_trans(thd);
}
} }
DBUG_RETURN(res); DBUG_RETURN(res);
...@@ -1101,6 +1122,27 @@ bool trans_xa_commit(THD *thd) ...@@ -1101,6 +1122,27 @@ bool trans_xa_commit(THD *thd)
else else
{ {
res= xa_trans_rolled_back(xs); res= xa_trans_rolled_back(xs);
/*
Acquire metadata lock which will ensure that COMMIT is blocked
by active FLUSH TABLES WITH READ LOCK (and vice versa COMMIT in
progress blocks FTWRL).
We allow FLUSHer to COMMIT; we assume FLUSHer knows what it does.
*/
MDL_request mdl_request;
mdl_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_COMMIT,
MDL_STATEMENT);
if (thd->mdl_context.acquire_lock(&mdl_request,
thd->variables.lock_wait_timeout))
{
/*
We can't rollback an XA transaction on lock failure due to
Innodb redo log and bin log update is involved in rollback.
Return error to user for a retry.
*/
my_error(ER_XAER_RMERR, MYF(0));
DBUG_RETURN(true);
}
ha_commit_or_rollback_by_xid(thd->lex->xid, !res); ha_commit_or_rollback_by_xid(thd->lex->xid, !res);
if((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) && if((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) &&
xs->is_binlogged) xs->is_binlogged)
...@@ -1139,13 +1181,18 @@ bool trans_xa_commit(THD *thd) ...@@ -1139,13 +1181,18 @@ bool trans_xa_commit(THD *thd)
We allow FLUSHer to COMMIT; we assume FLUSHer knows what it does. We allow FLUSHer to COMMIT; we assume FLUSHer knows what it does.
*/ */
mdl_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_COMMIT, mdl_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_COMMIT,
MDL_TRANSACTION); MDL_STATEMENT);
if (thd->mdl_context.acquire_lock(&mdl_request, if (thd->mdl_context.acquire_lock(&mdl_request,
thd->variables.lock_wait_timeout)) thd->variables.lock_wait_timeout))
{ {
ha_rollback_trans(thd, TRUE); /*
We can't rollback an XA transaction on lock failure due to
Innodb redo log and bin log update is involved in rollback.
Return error to user for a retry.
*/
my_error(ER_XAER_RMERR, MYF(0)); my_error(ER_XAER_RMERR, MYF(0));
DBUG_RETURN(true);
} }
else else
{ {
...@@ -1213,6 +1260,21 @@ bool trans_xa_rollback(THD *thd) ...@@ -1213,6 +1260,21 @@ bool trans_xa_rollback(THD *thd)
my_error(ER_XAER_NOTA, MYF(0)); my_error(ER_XAER_NOTA, MYF(0));
else else
{ {
MDL_request mdl_request;
mdl_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_COMMIT,
MDL_STATEMENT);
if (thd->mdl_context.acquire_lock(&mdl_request,
thd->variables.lock_wait_timeout))
{
/*
We can't rollback an XA transaction on lock failure due to
Innodb redo log and bin log update is involved in rollback.
Return error to user for a retry.
*/
my_error(ER_XAER_RMERR, MYF(0));
DBUG_RETURN(true);
}
xa_trans_rolled_back(xs); xa_trans_rolled_back(xs);
if (ha_commit_or_rollback_by_xid(thd->lex->xid, 0) == 0 && if (ha_commit_or_rollback_by_xid(thd->lex->xid, 0) == 0 &&
xs->is_binlogged && xs->is_binlogged &&
...@@ -1232,6 +1294,21 @@ bool trans_xa_rollback(THD *thd) ...@@ -1232,6 +1294,21 @@ bool trans_xa_rollback(THD *thd)
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
MDL_request mdl_request;
mdl_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_COMMIT,
MDL_STATEMENT);
if (thd->mdl_context.acquire_lock(&mdl_request,
thd->variables.lock_wait_timeout))
{
/*
We can't rollback an XA transaction on lock failure due to
Innodb redo log and bin log update is involved in rollback.
Return error to user for a retry.
*/
my_error(ER_XAER_RMERR, MYF(0));
DBUG_RETURN(true);
}
if(xa_state == XA_PREPARED && thd->transaction.xid_state.is_binlogged && if(xa_state == XA_PREPARED && thd->transaction.xid_state.is_binlogged &&
(WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open())) (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()))
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment