Let's consider the following test case in 10.2:
--source include/have_innodb.inc
|
--source include/not_embedded.inc
|
--source include/have_binlog_format_row.inc
|
--disable_warnings
|
drop table if exists t1, t2;
|
--enable_warnings
|
RESET MASTER;
|
create table t1 (a int) engine=innodb;
|
xa start 'test1';
|
insert t1 values (10);
|
xa end 'test1';
|
xa prepare 'test1';
|
|
--connect (con1,localhost,root,,)
|
--source include/kill_mysqld.inc
|
|
--let $restart_parameters= --tc-heuristic-recover=ROLLBACK
|
--source include/start_mysqld.inc
|
|
--exit
|
xarecover_handlerton() contains the following code:
for (int i=0; i < got; i ++)
|
{
|
my_xid x= WSREP_ON && wsrep_is_wsrep_xid(&info->list[i]) ?
|
wsrep_xid_seqno(info->list[i]) :
|
info->list[i].get_my_xid();
|
if (!x) // not "mine" - that is generated by external TM
|
{
|
#ifndef DBUG_OFF
|
char buf[XIDDATASIZE*4+6]; // see xid_to_str
|
DBUG_PRINT("info", ("ignore xid %s", xid_to_str(buf,
|
info->list+i)));
|
#endif
|
xid_cache_insert(info->list+i, XA_PREPARED);
|
info->found_foreign_xids++;
|
continue;
|
}
|
In the above test xid_t::get_my_xid() returns 0 (as the XID does not have MYSQL_XID_PREFIX prefix) for XID pushed in info->list by innodb(innobase_xa_prepare()). As a result, the XID is just pushed in xid_cache, and then XA transaction stays in prepared state independently on tc_heuristic_recover value.
Elkin confirmed this is correct behaviour.
There are two kinds of XA transactions:
1) client XA transactions, which are created explicitly by user with "XA start/end/prepare/commit/rollback" statements,
2) server XA transactions(with MYSQL_XID_PREFIX prefix in XID), which are created implicitly by the server to commit transaction in binary log and storage engine using two phase commit(see also innobase_xa_prepare()):
(gdb) bt
|
#0 binlog_prepare (hton=0x55555789f630, thd=0x7fff94000d50, all=false) at ./sql/log.cc:1927
|
#1 0x0000555555d70050 in prepare_or_error (ht=0x55555789f630, thd=0x7fff94000d50, all=false)
|
at ./sql/handler.cc:1195
|
#2 0x0000555555d70903 in ha_commit_trans (thd=0x7fff94000d50, all=false) at ./sql/handler.cc:1474
|
#3 0x0000555555c5bd7c in trans_commit_stmt (thd=0x7fff94000d50) at ./sql/transaction.cc:510
|
#4 0x0000555555b0523c in mysql_execute_command (thd=0x7fff94000d50) at ./sql/sql_parse.cc:6042
|
#5 0x0000555555b09c44 in mysql_parse (thd=0x7fff94000d50, rawbuf=0x7fff94013418 "INSERT INTO t1 VALUES (1)", length=25,
|
parser_state=0x7fffefd1c230, is_com_multi=false, is_next_command=false)
|
at ./sql/sql_parse.cc:7740
|
Client XA transactions are not rolled back or committed on recovery, they stays in prepared state independently on tc_heuristic_recover value until user commits or rolls them back manually. As I understood from our conversation with Elkin, this is intentional and correct behaviour.
So the solution with tc_heuristic_recover will not work. We could, for example, invoke innobase_rollback_by_xid() for prepared client transactions in mariabackup, but I am not sure this is correct behaviour, as there can be other storage engines involved in XA transaction.
Note that there is an active open issue that is being worked on related to --tc-heuristic-recover=ROLLBACK:
MDEV-21117