mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Merge from mysql-5.1-5.1.29-rc into mysql-5.1-bugteam
This commit is contained in:
@ -83,9 +83,57 @@ const LEX_STRING command_name[]={
|
||||
};
|
||||
|
||||
const char *xa_state_names[]={
|
||||
"NON-EXISTING", "ACTIVE", "IDLE", "PREPARED"
|
||||
"NON-EXISTING", "ACTIVE", "IDLE", "PREPARED", "ROLLBACK ONLY"
|
||||
};
|
||||
|
||||
/**
|
||||
Mark a XA transaction as rollback-only if the RM unilaterally
|
||||
rolled back the transaction branch.
|
||||
|
||||
@note If a rollback was requested by the RM, this function sets
|
||||
the appropriate rollback error code and transits the state
|
||||
to XA_ROLLBACK_ONLY.
|
||||
|
||||
@return TRUE if transaction was rolled back or if the transaction
|
||||
state is XA_ROLLBACK_ONLY. FALSE otherwise.
|
||||
*/
|
||||
static bool xa_trans_rolled_back(XID_STATE *xid_state)
|
||||
{
|
||||
if (xid_state->rm_error)
|
||||
{
|
||||
switch (xid_state->rm_error) {
|
||||
case ER_LOCK_WAIT_TIMEOUT:
|
||||
my_error(ER_XA_RBTIMEOUT, MYF(0));
|
||||
break;
|
||||
case ER_LOCK_DEADLOCK:
|
||||
my_error(ER_XA_RBDEADLOCK, MYF(0));
|
||||
break;
|
||||
default:
|
||||
my_error(ER_XA_RBROLLBACK, MYF(0));
|
||||
}
|
||||
xid_state->xa_state= XA_ROLLBACK_ONLY;
|
||||
}
|
||||
|
||||
return (xid_state->xa_state == XA_ROLLBACK_ONLY);
|
||||
}
|
||||
|
||||
/**
|
||||
Rollback work done on behalf of at ransaction branch.
|
||||
*/
|
||||
static bool xa_trans_rollback(THD *thd)
|
||||
{
|
||||
bool status= test(ha_rollback(thd));
|
||||
|
||||
thd->options&= ~(ulong) OPTION_BEGIN;
|
||||
thd->transaction.all.modified_non_trans_table= FALSE;
|
||||
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
|
||||
xid_cache_delete(&thd->transaction.xid_state);
|
||||
thd->transaction.xid_state.xa_state= XA_NOTR;
|
||||
thd->transaction.xid_state.rm_error= 0;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void unlock_locked_tables(THD *thd)
|
||||
{
|
||||
if (thd->locked_tables)
|
||||
@ -4507,6 +4555,7 @@ create_sp_error:
|
||||
}
|
||||
DBUG_ASSERT(thd->transaction.xid_state.xid.is_null());
|
||||
thd->transaction.xid_state.xa_state=XA_ACTIVE;
|
||||
thd->transaction.xid_state.rm_error= 0;
|
||||
thd->transaction.xid_state.xid.set(thd->lex->xid);
|
||||
xid_cache_insert(&thd->transaction.xid_state);
|
||||
thd->transaction.all.modified_non_trans_table= FALSE;
|
||||
@ -4532,6 +4581,8 @@ create_sp_error:
|
||||
my_error(ER_XAER_NOTA, MYF(0));
|
||||
break;
|
||||
}
|
||||
if (xa_trans_rolled_back(&thd->transaction.xid_state))
|
||||
break;
|
||||
thd->transaction.xid_state.xa_state=XA_IDLE;
|
||||
my_ok(thd);
|
||||
break;
|
||||
@ -4563,6 +4614,12 @@ create_sp_error:
|
||||
XID_STATE *xs=xid_cache_search(thd->lex->xid);
|
||||
if (!xs || xs->in_thd)
|
||||
my_error(ER_XAER_NOTA, MYF(0));
|
||||
else if (xa_trans_rolled_back(xs))
|
||||
{
|
||||
ha_commit_or_rollback_by_xid(thd->lex->xid, 0);
|
||||
xid_cache_delete(xs);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ha_commit_or_rollback_by_xid(thd->lex->xid, 1);
|
||||
@ -4571,6 +4628,11 @@ create_sp_error:
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (xa_trans_rolled_back(&thd->transaction.xid_state))
|
||||
{
|
||||
xa_trans_rollback(thd);
|
||||
break;
|
||||
}
|
||||
if (thd->transaction.xid_state.xa_state == XA_IDLE &&
|
||||
thd->lex->xa_opt == XA_ONE_PHASE)
|
||||
{
|
||||
@ -4617,28 +4679,26 @@ create_sp_error:
|
||||
my_error(ER_XAER_NOTA, MYF(0));
|
||||
else
|
||||
{
|
||||
bool ok= !xa_trans_rolled_back(xs);
|
||||
ha_commit_or_rollback_by_xid(thd->lex->xid, 0);
|
||||
xid_cache_delete(xs);
|
||||
my_ok(thd);
|
||||
if (ok)
|
||||
my_ok(thd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (thd->transaction.xid_state.xa_state != XA_IDLE &&
|
||||
thd->transaction.xid_state.xa_state != XA_PREPARED)
|
||||
thd->transaction.xid_state.xa_state != XA_PREPARED &&
|
||||
thd->transaction.xid_state.xa_state != XA_ROLLBACK_ONLY)
|
||||
{
|
||||
my_error(ER_XAER_RMFAIL, MYF(0),
|
||||
xa_state_names[thd->transaction.xid_state.xa_state]);
|
||||
break;
|
||||
}
|
||||
if (ha_rollback(thd))
|
||||
if (xa_trans_rollback(thd))
|
||||
my_error(ER_XAER_RMERR, MYF(0));
|
||||
else
|
||||
my_ok(thd);
|
||||
thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
|
||||
thd->transaction.all.modified_non_trans_table= FALSE;
|
||||
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
|
||||
xid_cache_delete(&thd->transaction.xid_state);
|
||||
thd->transaction.xid_state.xa_state=XA_NOTR;
|
||||
break;
|
||||
case SQLCOM_XA_RECOVER:
|
||||
res= mysql_xa_recover(thd);
|
||||
|
Reference in New Issue
Block a user