summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/sql_class.cc6
-rw-r--r--sql/xa.cc72
-rw-r--r--sql/xa.h1
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
}
diff --git a/sql/xa.h b/sql/xa.h
index bc916a6ba12..7cf74efad35 100644
--- a/sql/xa.h
+++ b/sql/xa.h
@@ -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);