diff options
author | Jon Olav Hauglid <jon.hauglid@oracle.com> | 2011-04-14 10:13:28 +0200 |
---|---|---|
committer | Jon Olav Hauglid <jon.hauglid@oracle.com> | 2011-04-14 10:13:28 +0200 |
commit | a5986fa220953d5d2faa5bb579a28b209bea6ebe (patch) | |
tree | b13ab6a189f59532be22d72322ce9ce171ff581d /sql/transaction.cc | |
parent | b71c5d51c6d91283fc3d656b70991319dfcc51f7 (diff) | |
download | mariadb-git-a5986fa220953d5d2faa5bb579a28b209bea6ebe.tar.gz |
Bug#12352846 - TRANS_XA_START(THD*):
ASSERTION THD->TRANSACTION.XID_STATE.XID.IS_NULL()
FAILED
The triggered assert checks that the previous XA transaction has
done proper cleanup before a new XA transaction is started.
The bug that caused it to be triggered was that XA COMMIT did not
clean up error state if XA COMMIT discovered that the current XA
transaction had to be rolled back.
This patch fixes the problem by resetting the XA error state
before XA COMMIT calls ha_rollback_trans(). This allows following
XA transactions to be started without triggering the assert.
Test case added to xa.test.
Diffstat (limited to 'sql/transaction.cc')
-rw-r--r-- | sql/transaction.cc | 40 |
1 files changed, 29 insertions, 11 deletions
diff --git a/sql/transaction.cc b/sql/transaction.cc index cd783e44792..94a32200274 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -79,6 +79,33 @@ static bool xa_trans_rolled_back(XID_STATE *xid_state) /** + Rollback the active XA transaction. + + @note Resets rm_error before calling ha_rollback(), so + the thd->transaction.xid structure gets reset + by ha_rollback() / THD::transaction::cleanup(). + + @return TRUE if the rollback failed, FALSE otherwise. +*/ + +static bool xa_trans_force_rollback(THD *thd) +{ + /* + We must reset rm_error before calling ha_rollback(), + so thd->transaction.xid structure gets reset + by ha_rollback()/THD::transaction::cleanup(). + */ + thd->transaction.xid_state.rm_error= 0; + if (ha_rollback_trans(thd, true)) + { + my_error(ER_XAER_RMERR, MYF(0)); + return true; + } + return false; +} + + +/** Begin a new transaction. @note Beginning a transaction implicitly commits any current @@ -649,8 +676,7 @@ bool trans_xa_commit(THD *thd) if (xa_trans_rolled_back(&thd->transaction.xid_state)) { - if (ha_rollback_trans(thd, TRUE)) - my_error(ER_XAER_RMERR, MYF(0)); + xa_trans_force_rollback(thd); res= thd->is_error(); } else if (xa_state == XA_IDLE && thd->lex->xa_opt == XA_ONE_PHASE) @@ -739,15 +765,7 @@ bool trans_xa_rollback(THD *thd) DBUG_RETURN(TRUE); } - /* - Resource Manager error is meaningless at this point, as we perform - explicit rollback request by user. We must reset rm_error before - calling ha_rollback(), so thd->transaction.xid structure gets reset - by ha_rollback()/THD::transaction::cleanup(). - */ - thd->transaction.xid_state.rm_error= 0; - if ((res= test(ha_rollback_trans(thd, TRUE)))) - my_error(ER_XAER_RMERR, MYF(0)); + res= xa_trans_force_rollback(thd); thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); thd->transaction.all.modified_non_trans_table= FALSE; |