MDEV-14609 XA Transction unable to ROLLBACK TO SAVEPOINT
The function trans_rollback_to_savepoint(), unlike trans_savepoint(), did not allow xa_state=XA_ACTIVE, so an attempt to do ROLLBCK TO SAVEPOINT inside an XA transaction incorrectly returned an error "...command cannot be executed ... in the ACTIVE state...". Partially merging a MySQL patch: 7fb5c47390311d9b1b5367f97cb8fedd4102dd05 This is WL#7193 (Decouple THD and st_transactions)... The currently merged part includes these changes: - Introducing st_xid_state::check_has_uncommitted_xa() - Reusing it in both trans_rollback_to_savepoint() and trans_savepoint(), so now both allow XA_ACTIVE.
This commit is contained in:
parent
5fe1d7d076
commit
88a9b23396
@ -200,6 +200,17 @@ a
|
||||
1
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-14609 XA Transction unable to ROLLBACK TO SAVEPOINT
|
||||
#
|
||||
CREATE TABLE t1 (c1 INT) ENGINE=INNODB;
|
||||
XA START 'xa1';
|
||||
SAVEPOINT savepoint1;
|
||||
INSERT INTO t1 (c1) VALUES (1),(2),(3),(4);
|
||||
ROLLBACK TO SAVEPOINT savepoint1;
|
||||
XA END 'xa1';
|
||||
XA ROLLBACK 'xa1';
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Bug#12352846 - TRANS_XA_START(THD*):
|
||||
# ASSERTION THD->TRANSACTION.XID_STATE.XID.IS_NULL()
|
||||
# FAILED
|
||||
|
@ -327,6 +327,20 @@ SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-14609 XA Transction unable to ROLLBACK TO SAVEPOINT
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (c1 INT) ENGINE=INNODB;
|
||||
XA START 'xa1';
|
||||
SAVEPOINT savepoint1;
|
||||
INSERT INTO t1 (c1) VALUES (1),(2),(3),(4);
|
||||
ROLLBACK TO SAVEPOINT savepoint1;
|
||||
XA END 'xa1';
|
||||
XA ROLLBACK 'xa1';
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Bug#12352846 - TRANS_XA_START(THD*):
|
||||
--echo # ASSERTION THD->TRANSACTION.XID_STATE.XID.IS_NULL()
|
||||
|
@ -991,6 +991,30 @@ typedef struct st_xid_state {
|
||||
bool in_thd;
|
||||
/* Error reported by the Resource Manager (RM) to the Transaction Manager. */
|
||||
uint rm_error;
|
||||
|
||||
/**
|
||||
Check that XA transaction has an uncommitted work. Report an error
|
||||
to the user in case when there is an uncommitted work for XA transaction.
|
||||
|
||||
@return result of check
|
||||
@retval false XA transaction is NOT in state IDLE, PREPARED
|
||||
or ROLLBACK_ONLY.
|
||||
@retval true XA transaction is in state IDLE or PREPARED
|
||||
or ROLLBACK_ONLY.
|
||||
*/
|
||||
|
||||
bool check_has_uncommitted_xa() const
|
||||
{
|
||||
if (xa_state == XA_IDLE ||
|
||||
xa_state == XA_PREPARED ||
|
||||
xa_state == XA_ROLLBACK_ONLY)
|
||||
{
|
||||
my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} XID_STATE;
|
||||
|
||||
extern mysql_mutex_t LOCK_xid_cache;
|
||||
|
@ -433,12 +433,8 @@ bool trans_savepoint(THD *thd, LEX_STRING name)
|
||||
!opt_using_transactions)
|
||||
DBUG_RETURN(FALSE);
|
||||
|
||||
enum xa_states xa_state= thd->transaction.xid_state.xa_state;
|
||||
if (xa_state != XA_NOTR && xa_state != XA_ACTIVE)
|
||||
{
|
||||
my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]);
|
||||
if (thd->transaction.xid_state.check_has_uncommitted_xa())
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
sv= find_savepoint(thd, name);
|
||||
|
||||
@ -513,12 +509,8 @@ bool trans_rollback_to_savepoint(THD *thd, LEX_STRING name)
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
enum xa_states xa_state= thd->transaction.xid_state.xa_state;
|
||||
if (xa_state != XA_NOTR)
|
||||
{
|
||||
my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]);
|
||||
if (thd->transaction.xid_state.check_has_uncommitted_xa())
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
if (ha_rollback_to_savepoint(thd, sv))
|
||||
res= TRUE;
|
||||
|
Loading…
x
Reference in New Issue
Block a user