diff options
author | Brandon Nesterenko <brandon.nesterenko@mariadb.com> | 2021-07-06 19:08:02 -0600 |
---|---|---|
committer | Brandon Nesterenko <brandon.nesterenko@mariadb.com> | 2021-07-06 19:08:02 -0600 |
commit | 170b5b8aaef97225af86e824b2ca39376f4cbb66 (patch) | |
tree | 27952d5d64e014d781aa31e249fef8fb164fe51f /sql/log.cc | |
parent | c262ccac027e71f22fc1329cf295a6bf687e4684 (diff) | |
download | mariadb-git-10.5-MDEV-25616.tar.gz |
MDEV-25616: Binlog event for XA COMMIT is generated without matching XA START, replication aborts10.5-MDEV-25616
Problem:
========
If the body of an XA transaction is empty, the XA COMMIT
event will be written into the binlog; however, no other
events will be added that relate to the transaction.
The body of an XA transaction is effectively empty if
all of its statements end in error.
Fix:
====
Ensure that the COMMIT is consistent with the other XA
statements so it is also not written into the binlog
Diffstat (limited to 'sql/log.cc')
-rw-r--r-- | sql/log.cc | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/sql/log.cc b/sql/log.cc index d9a271c56bd..28c3f1e78d9 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2194,7 +2194,21 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all) */ if (likely(!error) && ending_trans(thd, all)) { - error= is_preparing_xa(thd) ? + bool is_xa_prepare= is_preparing_xa(thd); + + if (!is_xa_prepare && !thd->transaction->all.is_trx_read_write()) + { + /* + If the transaction is empty, return and do not + log an XA COMMIT, as there will be no XA START + through XA PREPARE binlogged to accompany it. + */ + error= binlog_truncate_trx_cache(thd, cache_mngr, all); + THD_STAGE_INFO(thd, org_stage); + DBUG_RETURN(error); + } + + error= is_xa_prepare ? binlog_commit_flush_xa_prepare(thd, all, cache_mngr) : binlog_commit_flush_trx_cache (thd, all, cache_mngr); } @@ -2280,7 +2294,9 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) } else if (likely(!error)) { - if (ending_trans(thd, all) && trans_cannot_safely_rollback(thd, all)) + if (ending_trans(thd, all) && + trans_cannot_safely_rollback(thd, all) && + thd->transaction->all.is_trx_read_write()) error= binlog_rollback_flush_trx_cache(thd, all, cache_mngr); /* Truncate the cache if: |