# At a local mysql-6.0 repository of davi
2877 Davi Arnaut 2008-10-22 [merge]
Bug#28323: Server crashed in xid cache operations
The problem was that the server did not robustly handle a
unilateral roll back issued by the Resource Manager (RM)
due to a resource deadlock within the transaction branch.
By not acknowledging the roll back, the server (TM) would
eventually corrupt the XA transaction state and crash.
The solution is to mark the transaction as rollback-only
if the RM indicates that it rolled back its branch of the
modified:
mysql-test/r/backup_backupdir.result
mysql-test/r/debug_sync.result
mysql-test/r/locktrans_innodb.result
mysql-test/r/locktrans_myisam.result
mysql-test/r/xa.result
mysql-test/t/xa.test
sql/handler.cc
sql/share/errmsg.txt
sql/sql_class.h
sql/sql_parse.cc
sql/transaction.cc
per-file messages:
mysql-test/r/backup_backupdir.result
Update warning number due to new errors appearing earlier
in the list.
mysql-test/r/debug_sync.result
Update warning number due to new errors appearing earlier
in the list.
mysql-test/r/locktrans_innodb.result
Update warning number due to new errors appearing earlier
in the list.
mysql-test/r/locktrans_myisam.result
Update warning number due to new errors appearing earlier
in the list.
mysql-test/r/xa.result
Add test case result for Bug#28323
mysql-test/t/xa.test
Add test case for Bug#28323
sql/handler.cc
Reset XID only at the end of the global transaction.
sql/share/errmsg.txt
Add new error codes.
sql/sql_class.h
Remember the error reported by the Resource Manager.
sql/sql_parse.cc
Add new XA state.
sql/transaction.cc
Rollback the transaction if the Resource Manager reported
a error and rolled back its branch of the transaction.
=== modified file 'mysql-test/r/backup_backupdir.result'
--- a/mysql-test/r/backup_backupdir.result 2008-09-02 09:04:39 +0000
+++ b/mysql-test/r/backup_backupdir.result 2008-10-22 16:33:23 +0000
@@ -53,8 +53,8 @@ ERROR HY000: Can't write to backup locat
Attempt to set the backupdir to something invalid.
SET @@global.backupdir = 'This_is_really_stupid/not/there/at/all';
Warnings:
-Warning 1725 The path specified for the system variable backupdir cannot be accessed or is invalid. ref: This_is_really_stupid/not/there/at/all
-Warning 1725 The path specified for the system variable backupdir cannot be accessed or is invalid. ref: This_is_really_stupid/not/there/at/all
+Warning 1727 The path specified for the system variable backupdir cannot be accessed or is invalid. ref: This_is_really_stupid/not/there/at/all
+Warning 1727 The path specified for the system variable backupdir cannot be accessed or is invalid. ref: This_is_really_stupid/not/there/at/all
Cleanup
Reset backupdir
SET @@global.backupdir = @@global.datadir;
=== modified file 'mysql-test/r/debug_sync.result'
--- a/mysql-test/r/debug_sync.result 2008-07-09 14:27:18 +0000
+++ b/mysql-test/r/debug_sync.result 2008-10-22 16:33:23 +0000
@@ -137,7 +137,7 @@ Variable_name Value
debug_sync ON - current signal: 'something'
SET DEBUG_SYNC= 'now WAIT_FOR nothing TIMEOUT 0';
Warnings:
-Warning 1720 debug sync point wait timed out
+Warning 1722 debug sync point wait timed out
SET DEBUG_SYNC= 'now SIGNAL nothing';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
Variable_name Value
=== modified file 'mysql-test/r/locktrans_innodb.result'
--- a/mysql-test/r/locktrans_innodb.result 2008-06-26 18:56:36 +0000
+++ b/mysql-test/r/locktrans_innodb.result 2008-10-22 16:33:23 +0000
@@ -95,12 +95,12 @@ ERROR 42000: You have an error in your S
# Implicit lock method conversion due to mix in statement.
LOCK TABLE t1 READ, t2 IN EXCLUSIVE MODE;
Warnings:
-Warning 1615 Converted to non-transactional lock on 't2'
+Warning 1617 Converted to non-transactional lock on 't2'
UNLOCK TABLES;
# Lock t1 share (converted to read), t2 write.
LOCK TABLE t1 IN SHARE MODE, t2 WRITE;
Warnings:
-Warning 1615 Converted to non-transactional lock on 't1'
+Warning 1617 Converted to non-transactional lock on 't1'
# Show t1 is read locked, t2 write locked.
INSERT INTO t1 SELECT * FROM t2;
ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
@@ -111,8 +111,8 @@ INSERT INTO t2 SELECT * FROM t1;
# Lock t1 exclusive (converted to write), t2 share (converted to read).
LOCK TABLE t1 IN EXCLUSIVE MODE, t2 IN SHARE MODE;
Warnings:
-Warning 1615 Converted to non-transactional lock on 't1'
-Warning 1615 Converted to non-transactional lock on 't2'
+Warning 1617 Converted to non-transactional lock on 't1'
+Warning 1617 Converted to non-transactional lock on 't2'
# Show t1 is write locked, t2 read locked.
INSERT INTO t1 SELECT * FROM t2;
INSERT INTO t2 SELECT * FROM t1;
@@ -136,8 +136,8 @@ ERROR HY000: Cannot convert to non-trans
## Error is reported on first table only. Show both errors:
SHOW WARNINGS;
Level Code Message
-Error 1616 Cannot convert to non-transactional lock in strict mode on 't1'
-Error 1616 Cannot convert to non-transactional lock in strict mode on 't2'
+Error 1618 Cannot convert to non-transactional lock in strict mode on 't1'
+Error 1618 Cannot convert to non-transactional lock in strict mode on 't2'
UNLOCK TABLES;
SET @@SQL_MODE= @wl3561_save_sql_mode;
#
@@ -157,7 +157,7 @@ CREATE TABLE t4 (c4 INT) ENGINE= MyISAM;
# Request a transactional lock, which is converted to non-transactional.
LOCK TABLE t4 IN SHARE MODE;
Warnings:
-Warning 1615 Converted to non-transactional lock on 't4'
+Warning 1617 Converted to non-transactional lock on 't4'
# Try a conflict with the existing non-transactional lock.
INSERT INTO t4 VALUES(444);
ERROR HY000: Table 't4' was locked with a READ lock and can't be updated
@@ -174,8 +174,8 @@ CREATE VIEW v1 AS SELECT * FROM t3, t4 W
# Request a share lock on the view, which is converted to read locks.
LOCK TABLE v1 IN SHARE MODE;
Warnings:
-Warning 1615 Converted to non-transactional lock on 't3'
-Warning 1615 Converted to non-transactional lock on 't4'
+Warning 1617 Converted to non-transactional lock on 't3'
+Warning 1617 Converted to non-transactional lock on 't4'
# Show that read locks on the base tables prohibit writing ...
INSERT INTO t3 SELECT * FROM t4;
ERROR HY000: Table 't3' was locked with a READ lock and can't be updated
@@ -191,7 +191,7 @@ COUNT(*)
## Report conversion on view due to existing non-transactional locks.
LOCK TABLE v1 IN EXCLUSIVE MODE;
Warnings:
-Warning 1615 Converted to non-transactional lock on 'v1'
+Warning 1617 Converted to non-transactional lock on 'v1'
INSERT INTO t3 VALUES(333);
INSERT INTO t4 VALUES(444);
INSERT INTO t1 VALUES(111);
@@ -200,8 +200,8 @@ UNLOCK TABLES;
## Now report conversion on base table again.
LOCK TABLE v1 IN EXCLUSIVE MODE;
Warnings:
-Warning 1615 Converted to non-transactional lock on 't3'
-Warning 1615 Converted to non-transactional lock on 't4'
+Warning 1617 Converted to non-transactional lock on 't3'
+Warning 1617 Converted to non-transactional lock on 't4'
INSERT INTO t3 VALUES(333);
INSERT INTO t4 VALUES(444);
INSERT INTO t1 VALUES(111);
=== modified file 'mysql-test/r/locktrans_myisam.result'
--- a/mysql-test/r/locktrans_myisam.result 2008-06-26 18:56:36 +0000
+++ b/mysql-test/r/locktrans_myisam.result 2008-10-22 16:33:23 +0000
@@ -21,8 +21,8 @@ UNLOCK TABLES;
# Valid syntax for transactional locks.
LOCK TABLE t1 IN SHARE MODE, t2 IN EXCLUSIVE MODE;
Warnings:
-Warning 1615 Converted to non-transactional lock on 't1'
-Warning 1615 Converted to non-transactional lock on 't2'
+Warning 1617 Converted to non-transactional lock on 't1'
+Warning 1617 Converted to non-transactional lock on 't2'
UNLOCK TABLES;
#
# Valid syntax for aliases with and without 'AS'.
@@ -30,19 +30,19 @@ LOCK TABLE t1 AS a1 READ, t2 a2 WRITE;
UNLOCK TABLES;
LOCK TABLE t1 AS a1 IN SHARE MODE, t2 a2 IN EXCLUSIVE MODE;
Warnings:
-Warning 1615 Converted to non-transactional lock on 'a1'
-Warning 1615 Converted to non-transactional lock on 'a2'
+Warning 1617 Converted to non-transactional lock on 'a1'
+Warning 1617 Converted to non-transactional lock on 'a2'
UNLOCK TABLES;
#
# Transactional locks taken on a view.
CREATE VIEW v1 AS SELECT * FROM t1, t2 WHERE t1.c1 = t2.c2;
LOCK TABLE v1 IN SHARE MODE;
Warnings:
-Warning 1615 Converted to non-transactional lock on 't1'
-Warning 1615 Converted to non-transactional lock on 't2'
+Warning 1617 Converted to non-transactional lock on 't1'
+Warning 1617 Converted to non-transactional lock on 't2'
LOCK TABLE v1 IN EXCLUSIVE MODE;
Warnings:
-Warning 1615 Converted to non-transactional lock on 'v1'
+Warning 1617 Converted to non-transactional lock on 'v1'
UNLOCK TABLES;
DROP VIEW v1;
#
@@ -95,12 +95,12 @@ ERROR 42000: You have an error in your S
# Implicit lock method conversion due to mix in statement.
LOCK TABLE t1 READ, t2 IN EXCLUSIVE MODE;
Warnings:
-Warning 1615 Converted to non-transactional lock on 't2'
+Warning 1617 Converted to non-transactional lock on 't2'
UNLOCK TABLES;
# Lock t1 share (converted to read), t2 write.
LOCK TABLE t1 IN SHARE MODE, t2 WRITE;
Warnings:
-Warning 1615 Converted to non-transactional lock on 't1'
+Warning 1617 Converted to non-transactional lock on 't1'
# Show t1 is read locked, t2 write locked.
INSERT INTO t1 SELECT * FROM t2;
ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
@@ -111,8 +111,8 @@ INSERT INTO t2 SELECT * FROM t1;
# Lock t1 exclusive (converted to write), t2 share (converted to read).
LOCK TABLE t1 IN EXCLUSIVE MODE, t2 IN SHARE MODE;
Warnings:
-Warning 1615 Converted to non-transactional lock on 't1'
-Warning 1615 Converted to non-transactional lock on 't2'
+Warning 1617 Converted to non-transactional lock on 't1'
+Warning 1617 Converted to non-transactional lock on 't2'
# Show t1 is write locked, t2 read locked.
INSERT INTO t1 SELECT * FROM t2;
INSERT INTO t2 SELECT * FROM t1;
@@ -136,8 +136,8 @@ ERROR HY000: Cannot convert to non-trans
## Error is reported on first table only. Show both errors:
SHOW WARNINGS;
Level Code Message
-Error 1616 Cannot convert to non-transactional lock in strict mode on 't1'
-Error 1616 Cannot convert to non-transactional lock in strict mode on 't2'
+Error 1618 Cannot convert to non-transactional lock in strict mode on 't1'
+Error 1618 Cannot convert to non-transactional lock in strict mode on 't2'
UNLOCK TABLES;
SET @@SQL_MODE= @wl3561_save_sql_mode;
#
@@ -157,7 +157,7 @@ CREATE TABLE t4 (c4 INT) ENGINE= MyISAM;
# Request a transactional lock, which is converted to non-transactional.
LOCK TABLE t4 IN SHARE MODE;
Warnings:
-Warning 1615 Converted to non-transactional lock on 't4'
+Warning 1617 Converted to non-transactional lock on 't4'
# Try a conflict with the existing non-transactional lock.
INSERT INTO t4 VALUES(444);
ERROR HY000: Table 't4' was locked with a READ lock and can't be updated
@@ -174,8 +174,8 @@ CREATE VIEW v1 AS SELECT * FROM t3, t4 W
# Request a share lock on the view, which is converted to read locks.
LOCK TABLE v1 IN SHARE MODE;
Warnings:
-Warning 1615 Converted to non-transactional lock on 't3'
-Warning 1615 Converted to non-transactional lock on 't4'
+Warning 1617 Converted to non-transactional lock on 't3'
+Warning 1617 Converted to non-transactional lock on 't4'
# Show that read locks on the base tables prohibit writing ...
INSERT INTO t3 SELECT * FROM t4;
ERROR HY000: Table 't3' was locked with a READ lock and can't be updated
@@ -191,7 +191,7 @@ COUNT(*)
## Report conversion on view due to existing non-transactional locks.
LOCK TABLE v1 IN EXCLUSIVE MODE;
Warnings:
-Warning 1615 Converted to non-transactional lock on 'v1'
+Warning 1617 Converted to non-transactional lock on 'v1'
INSERT INTO t3 VALUES(333);
INSERT INTO t4 VALUES(444);
INSERT INTO t1 VALUES(111);
@@ -200,8 +200,8 @@ UNLOCK TABLES;
## Now report conversion on base table again.
LOCK TABLE v1 IN EXCLUSIVE MODE;
Warnings:
-Warning 1615 Converted to non-transactional lock on 't3'
-Warning 1615 Converted to non-transactional lock on 't4'
+Warning 1617 Converted to non-transactional lock on 't3'
+Warning 1617 Converted to non-transactional lock on 't4'
INSERT INTO t3 VALUES(333);
INSERT INTO t4 VALUES(444);
INSERT INTO t1 VALUES(111);
=== modified file 'mysql-test/r/xa.result'
--- a/mysql-test/r/xa.result 2005-10-05 17:58:16 +0000
+++ b/mysql-test/r/xa.result 2008-10-21 21:02:26 +0000
@@ -55,3 +55,23 @@ select * from t1;
a
20
drop table t1;
+drop table if exists t1;
+create table t1(a int, b int, c varchar(20), primary key(a)) engine = innodb;
+insert into t1 values(1, 1, 'a');
+insert into t1 values(2, 2, 'b');
+xa start 'a','b';
+update t1 set c = 'aa' where a = 1;
+xa start 'a','c';
+update t1 set c = 'bb' where a = 2;
+update t1 set c = 'bb' where a = 2;
+update t1 set c = 'aa' where a = 1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+select count(*) from t1;
+count(*)
+2
+xa end 'a','c';
+ERROR XA102: XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected
+xa rollback 'a','c';
+xa start 'a','c';
+drop table t1;
+End of 5.0 tests
=== modified file 'mysql-test/t/xa.test'
--- a/mysql-test/t/xa.test 2007-02-26 10:49:24 +0000
+++ b/mysql-test/t/xa.test 2008-10-21 21:02:26 +0000
@@ -74,3 +74,48 @@ xa start 'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
select * from t1;
drop table t1;
+disconnect con1;
+
+#
+# Bug#28323: Server crashed in xid cache operations
+#
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+create table t1(a int, b int, c varchar(20), primary key(a)) engine = innodb;
+insert into t1 values(1, 1, 'a');
+insert into t1 values(2, 2, 'b');
+
+connect (con1,localhost,root,,);
+connect (con2,localhost,root,,);
+
+--connection con1
+xa start 'a','b';
+update t1 set c = 'aa' where a = 1;
+--connection con2
+xa start 'a','c';
+update t1 set c = 'bb' where a = 2;
+--connection con1
+--send update t1 set c = 'bb' where a = 2
+--connection con2
+--sleep 1
+--error ER_LOCK_DEADLOCK
+update t1 set c = 'aa' where a = 1;
+select count(*) from t1;
+--error ER_XA_RBDEADLOCK
+xa end 'a','c';
+xa rollback 'a','c';
+--disconnect con2
+
+connect (con3,localhost,root,,);
+--connection con3
+xa start 'a','c';
+
+--disconnect con1
+--disconnect con3
+--connection default
+drop table t1;
+
+--echo End of 5.0 tests
=== modified file 'sql/handler.cc'
--- a/sql/handler.cc 2008-10-08 13:55:20 +0000
+++ b/sql/handler.cc 2008-10-22 16:33:23 +0000
@@ -1288,7 +1288,12 @@ int ha_rollback_trans(THD *thd, bool all
trans->ha_list= 0;
trans->no_2pc=0;
if (is_real_trans)
- thd->transaction.xid_state.xid.null();
+ {
+ if (thd->transaction_rollback_request)
+ thd->transaction.xid_state.rm_error= thd->main_da.sql_errno();
+ else
+ thd->transaction.xid_state.xid.null();
+ }
if (all)
{
thd->variables.tx_isolation=thd->session_tx_isolation;
=== modified file 'sql/share/errmsg.txt'
--- a/sql/share/errmsg.txt 2008-09-03 12:39:48 +0000
+++ b/sql/share/errmsg.txt 2008-10-22 16:33:23 +0000
@@ -6128,6 +6128,12 @@ ER_LOAD_DATA_INVALID_COLUMN
ER_LOG_PURGE_NO_FILE
eng "Being purged log %s was not found"
+ER_XA_RBTIMEOUT XA106
+ eng "XA_RBTIMEOUT: Transaction branch was rolled back: took too long"
+
+ER_XA_RBDEADLOCK XA102
+ eng "XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected"
+
ER_NEED_REPREPARE
eng "Prepared statement needs to be re-prepared"
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2008-10-09 12:48:49 +0000
+++ b/sql/sql_class.h 2008-10-22 16:33:23 +0000
@@ -794,7 +794,7 @@ struct st_savepoint {
Ha_trx_info *ha_list;
};
-enum xa_states {XA_NOTR=0, XA_ACTIVE, XA_IDLE, XA_PREPARED};
+enum xa_states {XA_NOTR=0, XA_ACTIVE, XA_IDLE, XA_PREPARED, XA_ROLLBACK_ONLY};
extern const char *xa_state_names[];
typedef struct st_xid_state {
@@ -802,6 +802,8 @@ typedef struct st_xid_state {
XID xid; // transaction identifier
enum xa_states xa_state; // used by external XA only
bool in_thd;
+ /* Error reported by the Resource Manager (RM) to the Transaction Manager. */
+ uint rm_error;
} XID_STATE;
extern pthread_mutex_t LOCK_xid_cache;
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2008-10-08 11:46:49 +0000
+++ b/sql/sql_parse.cc 2008-10-22 16:33:23 +0000
@@ -94,7 +94,7 @@ const LEX_STRING command_name[]={
};
const char *xa_state_names[]={
- "NON-EXISTING", "ACTIVE", "IDLE", "PREPARED"
+ "NON-EXISTING", "ACTIVE", "IDLE", "PREPARED", "ROLLBACK ONLY"
};
extern DDL_blocker_class *DDL_blocker;
=== modified file 'sql/transaction.cc'
--- a/sql/transaction.cc 2008-09-23 14:33:18 +0000
+++ b/sql/transaction.cc 2008-10-22 16:33:23 +0000
@@ -44,6 +44,38 @@ static bool trans_check(THD *thd)
/**
+ 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);
+}
+
+
+/**
Begin a new transaction.
@note Beginning a transaction implicitly commits any current
@@ -229,7 +261,6 @@ bool trans_rollback_stmt(THD *thd)
if (thd->transaction.stmt.ha_list)
{
- thd->transaction_rollback_request= FALSE;
ha_rollback_trans(thd, FALSE);
if (thd->transaction_rollback_request && !thd->in_sub_stmt)
ha_rollback_trans(thd, TRUE);
@@ -426,6 +457,7 @@ bool trans_xa_start(THD *thd)
{
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);
DBUG_RETURN(FALSE);
@@ -456,7 +488,7 @@ bool trans_xa_end(THD *thd)
xa_state_names[thd->transaction.xid_state.xa_state]);
else if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
my_error(ER_XAER_NOTA, MYF(0));
- else
+ else if (!xa_trans_rolled_back(&thd->transaction.xid_state))
thd->transaction.xid_state.xa_state= XA_IDLE;
DBUG_RETURN(thd->transaction.xid_state.xa_state != XA_IDLE);
@@ -512,18 +544,24 @@ bool trans_xa_commit(THD *thd)
if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
{
XID_STATE *xs= xid_cache_search(thd->lex->xid);
- bool not_found= !xs || xs->in_thd;
- if (not_found)
+ res= !xs || xs->in_thd;
+ if (res)
my_error(ER_XAER_NOTA, MYF(0));
else
{
- ha_commit_or_rollback_by_xid(thd->lex->xid, 1);
+ res= xa_trans_rolled_back(xs);
+ ha_commit_or_rollback_by_xid(thd->lex->xid, !res);
xid_cache_delete(xs);
}
- DBUG_RETURN(not_found);
+ DBUG_RETURN(res);
}
- if (xa_state == XA_IDLE && thd->lex->xa_opt == XA_ONE_PHASE)
+ if (xa_trans_rolled_back(&thd->transaction.xid_state))
+ {
+ if ((res= test(ha_rollback_trans(thd, TRUE))))
+ my_error(ER_XAER_RMERR, MYF(0));
+ }
+ else if (xa_state == XA_IDLE && thd->lex->xa_opt == XA_ONE_PHASE)
{
int r= ha_commit_trans(thd, TRUE);
if ((res= test(r)))
@@ -545,7 +583,10 @@ bool trans_xa_commit(THD *thd)
}
}
else
+ {
my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]);
+ DBUG_RETURN(TRUE);
+ }
thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
thd->transaction.all.modified_non_trans_table= FALSE;
@@ -575,18 +616,18 @@ bool trans_xa_rollback(THD *thd)
if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
{
XID_STATE *xs= xid_cache_search(thd->lex->xid);
- bool not_found= !xs || xs->in_thd;
- if (not_found)
+ if (!xs || xs->in_thd)
my_error(ER_XAER_NOTA, MYF(0));
else
{
+ xa_trans_rolled_back(xs);
ha_commit_or_rollback_by_xid(thd->lex->xid, 0);
xid_cache_delete(xs);
}
- DBUG_RETURN(not_found);
+ DBUG_RETURN(thd->main_da.is_error());
}
- if (xa_state != XA_IDLE && xa_state != XA_PREPARED)
+ 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]);
DBUG_RETURN(TRUE);
| Thread |
|---|
| • bzr commit into mysql-6.0 branch (davi:2877) Bug#28323 | Davi Arnaut | 22 Oct |