diff options
author | Sergey Vojtovich <svoj@mariadb.org> | 2019-04-22 00:04:14 +0400 |
---|---|---|
committer | Sergey Vojtovich <svoj@mariadb.org> | 2019-04-25 15:06:40 +0400 |
commit | 1599825ffc2c942f8b63274a9556b425229375c7 (patch) | |
tree | 17a95099e6317b796f5715a3462b7a271bf55fa1 | |
parent | 210855ce5d6803f41d672d75be3334726f52a9df (diff) | |
download | mariadb-git-1599825ffc2c942f8b63274a9556b425229375c7.tar.gz |
trans_xa_detach() framework
Part of MDEV-7974 - backport fix for mysql bug#12161 (XA and binlog)
-rw-r--r-- | sql/sql_class.cc | 6 | ||||
-rw-r--r-- | sql/xa.cc | 72 | ||||
-rw-r--r-- | sql/xa.h | 1 |
3 files changed, 56 insertions, 23 deletions
diff --git a/sql/sql_class.cc b/sql/sql_class.cc index a32d4bad5d2..0e0eda8cc21 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1525,8 +1525,10 @@ void THD::cleanup(void) delete_dynamic(&user_var_events); close_temporary_tables(); - xid_cache_delete(this, &transaction.xid_state); - trans_rollback(this); + if (transaction.xid_state.is_explicit_XA()) + trans_xa_detach(this); + else + trans_rollback(this); DBUG_ASSERT(open_tables == NULL); /* diff --git a/sql/xa.cc b/sql/xa.cc index 64efa06253a..c4b983aa4f5 100644 --- a/sql/xa.cc +++ b/sql/xa.cc @@ -106,11 +106,16 @@ public: (void) LF_BACKOFF(); } } + void acquired_to_recovered() + { + m_state.fetch_or(RECOVERED, std::memory_order_relaxed); + m_state.fetch_and(~ACQUIRED, std::memory_order_release); + } bool acquire_recovered() { int32_t old= RECOVERED; while (!m_state.compare_exchange_weak(old, ACQUIRED | RECOVERED, - std::memory_order_relaxed, + std::memory_order_acquire, std::memory_order_relaxed)) { if (!(old & RECOVERED) || (old & ACQUIRED)) @@ -303,11 +308,9 @@ static void xid_cache_delete(THD *thd, XID_cache_element *&element) void xid_cache_delete(THD *thd, XID_STATE *xid_state) { - if (xid_state->xid_cache_element) - { - xid_cache_delete(thd, xid_state->xid_cache_element); - xid_state->xid_cache_element= 0; - } + DBUG_ASSERT(xid_state->is_explicit_XA()); + xid_cache_delete(thd, xid_state->xid_cache_element); + xid_state->xid_cache_element= 0; } @@ -379,12 +382,24 @@ static bool xa_trans_rolled_back(XID_cache_element *element) static bool xa_trans_force_rollback(THD *thd) { + bool rc= false; + if (ha_rollback_trans(thd, true)) { my_error(ER_XAER_RMERR, MYF(0)); - return true; + rc= true; } - return false; + + 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); + DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); + xid_cache_delete(thd, &thd->transaction.xid_state); + + trans_track_end_trx(thd); + + return rc; } @@ -532,7 +547,7 @@ bool trans_xa_commit(THD *thd) if (xa_trans_rolled_back(thd->transaction.xid_state.xid_cache_element)) { xa_trans_force_rollback(thd); - res= thd->is_error(); + DBUG_RETURN(thd->is_error()); } else if (thd->transaction.xid_state.xid_cache_element->xa_state == XA_IDLE && thd->lex->xa_opt == XA_ONE_PHASE) @@ -601,7 +616,6 @@ bool trans_xa_commit(THD *thd) bool trans_xa_rollback(THD *thd) { - bool res= TRUE; DBUG_ENTER("trans_xa_rollback"); if (!thd->transaction.xid_state.is_explicit_XA() || @@ -629,19 +643,35 @@ bool trans_xa_rollback(THD *thd) thd->transaction.xid_state.er_xaer_rmfail(); DBUG_RETURN(TRUE); } + DBUG_RETURN(xa_trans_force_rollback(thd)); +} - res= xa_trans_force_rollback(thd); - - 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); - DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); - xid_cache_delete(thd, &thd->transaction.xid_state); - - trans_track_end_trx(thd); - DBUG_RETURN(res); +bool trans_xa_detach(THD *thd) +{ + DBUG_ASSERT(thd->transaction.xid_state.is_explicit_XA()); +#if 1 + return xa_trans_force_rollback(thd); +#else + if (thd->transaction.xid_state.xid_cache_element->xa_state != XA_PREPARED) + return xa_trans_force_rollback(thd); + thd->transaction.xid_state.xid_cache_element->acquired_to_recovered(); + thd->transaction.xid_state.xid_cache_element= 0; + thd->transaction.cleanup(); + + Ha_trx_info *ha_info, *ha_info_next; + for (ha_info= thd->transaction.all.ha_list; + ha_info; + ha_info= ha_info_next) + { + ha_info_next= ha_info->next(); + ha_info->reset(); /* keep it conveniently zero-filled */ + } + + thd->transaction.all.ha_list= 0; + thd->transaction.all.no_2pc= 0; + return false; +#endif } @@ -40,4 +40,5 @@ bool trans_xa_end(THD *thd); bool trans_xa_prepare(THD *thd); bool trans_xa_commit(THD *thd); bool trans_xa_rollback(THD *thd); +bool trans_xa_detach(THD *thd); bool mysql_xa_recover(THD *thd); |