This patch fixes bug#14729757 - MY_HASH_SEARCH(&XID_CACHE,
XID_STATE->XID.KEY(), XID_STATE->XID.KEY_LENGTH())==0 This bug is a regression of bug#11759534 - 51855: RACE CONDITION IN XA START. The reason for regression is that the changes that fixes the original bug wasn't merged from mysql-5.1 into mysql-5.5 and mysql-trunk. Only null-merge was done for the patch changeset. To incorporate lost changes the manual merge have been done. Additionally the call of trans_rolback() was added into trans_xa_start() in case if xid_cache_insert is failed() after transaction has been started. If we don't call trans_rollback() we would never reset the flag SERVER_STATUS_IN_TRANS in THD::server_status and therefore all subsequent attempts to execute XA START in the connection where the error was occurred will be failed since thd->in_active_multi_stmt_transaction() will return the true every time when trans_xa_start is called. The latest changes were absent in patch for mysql-5.1
This commit is contained in:
parent
38457c1a5f
commit
0109a65cb9
@ -4024,9 +4024,14 @@ bool xid_cache_insert(XID *xid, enum xa_states xa_state)
|
|||||||
bool xid_cache_insert(XID_STATE *xid_state)
|
bool xid_cache_insert(XID_STATE *xid_state)
|
||||||
{
|
{
|
||||||
mysql_mutex_lock(&LOCK_xid_cache);
|
mysql_mutex_lock(&LOCK_xid_cache);
|
||||||
DBUG_ASSERT(my_hash_search(&xid_cache, xid_state->xid.key(),
|
if (my_hash_search(&xid_cache, xid_state->xid.key(),
|
||||||
xid_state->xid.key_length())==0);
|
xid_state->xid.key_length()))
|
||||||
my_bool res=my_hash_insert(&xid_cache, (uchar*)xid_state);
|
{
|
||||||
|
mysql_mutex_unlock(&LOCK_xid_cache);
|
||||||
|
my_error(ER_XAER_DUPID, MYF(0));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool res= my_hash_insert(&xid_cache, (uchar*)xid_state);
|
||||||
mysql_mutex_unlock(&LOCK_xid_cache);
|
mysql_mutex_unlock(&LOCK_xid_cache);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -567,15 +567,19 @@ bool trans_xa_start(THD *thd)
|
|||||||
my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]);
|
my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]);
|
||||||
else if (thd->locked_tables_mode || thd->in_active_multi_stmt_transaction())
|
else if (thd->locked_tables_mode || thd->in_active_multi_stmt_transaction())
|
||||||
my_error(ER_XAER_OUTSIDE, MYF(0));
|
my_error(ER_XAER_OUTSIDE, MYF(0));
|
||||||
else if (xid_cache_search(thd->lex->xid))
|
|
||||||
my_error(ER_XAER_DUPID, MYF(0));
|
|
||||||
else if (!trans_begin(thd))
|
else if (!trans_begin(thd))
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(thd->transaction.xid_state.xid.is_null());
|
DBUG_ASSERT(thd->transaction.xid_state.xid.is_null());
|
||||||
thd->transaction.xid_state.xa_state= XA_ACTIVE;
|
thd->transaction.xid_state.xa_state= XA_ACTIVE;
|
||||||
thd->transaction.xid_state.rm_error= 0;
|
thd->transaction.xid_state.rm_error= 0;
|
||||||
thd->transaction.xid_state.xid.set(thd->lex->xid);
|
thd->transaction.xid_state.xid.set(thd->lex->xid);
|
||||||
xid_cache_insert(&thd->transaction.xid_state);
|
if (xid_cache_insert(&thd->transaction.xid_state))
|
||||||
|
{
|
||||||
|
thd->transaction.xid_state.xa_state= XA_NOTR;
|
||||||
|
thd->transaction.xid_state.xid.null();
|
||||||
|
trans_rollback(thd);
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
}
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -661,6 +665,16 @@ bool trans_xa_commit(THD *thd)
|
|||||||
|
|
||||||
if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
|
if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
xid_state.in_thd is always true beside of xa recovery procedure.
|
||||||
|
Note, that there is no race condition here between xid_cache_search
|
||||||
|
and xid_cache_delete, since we always delete our own XID
|
||||||
|
(thd->lex->xid == thd->transaction.xid_state.xid).
|
||||||
|
The only case when thd->lex->xid != thd->transaction.xid_state.xid
|
||||||
|
and xid_state->in_thd == 0 is in the function
|
||||||
|
xa_cache_insert(XID, xa_states), which is called before starting
|
||||||
|
client connections, and thus is always single-threaded.
|
||||||
|
*/
|
||||||
XID_STATE *xs= xid_cache_search(thd->lex->xid);
|
XID_STATE *xs= xid_cache_search(thd->lex->xid);
|
||||||
res= !xs || xs->in_thd;
|
res= !xs || xs->in_thd;
|
||||||
if (res)
|
if (res)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user