diff --git a/mysql-test/suite/innodb/r/innodb-xa.result b/mysql-test/suite/innodb/r/innodb-xa.result new file mode 100644 index 00000000000..6eae842b14c --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb-xa.result @@ -0,0 +1,17 @@ +xa rollback 'xid2'; +ERROR XAE04: XAER_NOTA: Unknown XID +drop table if exists t1; +Warnings: +Note 1051 Unknown table 'test.t1' +create table t1(a int)engine=innodb; +rollback; +xa start 'xid2'; +insert into `t1` values (1); +savepoint `sv1`; +xa end 'xid2'; +start transaction; +ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the IDLE state +xa prepare 'xid2'; +release savepoint `sv1`; +xa commit 'xid2'; +drop table t1; diff --git a/mysql-test/suite/innodb/t/innodb-xa.test b/mysql-test/suite/innodb/t/innodb-xa.test new file mode 100644 index 00000000000..d94cd75aa14 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-xa.test @@ -0,0 +1,17 @@ +--source include/have_innodb.inc + +--disable_abort_on_error +xa rollback 'xid2'; +drop table if exists t1; +create table t1(a int)engine=innodb; +rollback; +xa start 'xid2'; +insert into `t1` values (1); +savepoint `sv1`; +xa end 'xid2'; +start transaction; +xa prepare 'xid2'; +release savepoint `sv1`; +xa commit 'xid2'; +drop table t1; + diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index e86949198f8..de78a39f154 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4116,7 +4116,10 @@ innobase_release_savepoint( DBUG_ASSERT(hton == innodb_hton_ptr); trx = check_trx_exists(thd); - trx_start_if_not_started(trx); + + if (trx->state == TRX_STATE_NOT_STARTED) { + trx_start_if_not_started(trx); + } /* TODO: use provided savepoint data area to store savepoint data */ diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index bc11f1d76bd..e2c3c0b949c 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -495,7 +495,7 @@ trx_release_savepoint_for_mysql( { trx_named_savept_t* savep; - ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE)); + ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE) || trx_state_eq(trx, TRX_STATE_PREPARED)); ut_ad(trx->in_mysql_trx_list); savep = trx_savepoint_find(trx, savepoint_name); diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 88ecb584475..ecc3d1c17eb 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -4679,7 +4679,10 @@ innobase_release_savepoint( DBUG_ASSERT(hton == innodb_hton_ptr); trx = check_trx_exists(thd); - trx_start_if_not_started(trx); + + if (trx->state == TRX_STATE_NOT_STARTED) { + trx_start_if_not_started(trx); + } /* TODO: use provided savepoint data area to store savepoint data */ diff --git a/storage/xtradb/trx/trx0roll.cc b/storage/xtradb/trx/trx0roll.cc index a64367c4ba7..79379741493 100644 --- a/storage/xtradb/trx/trx0roll.cc +++ b/storage/xtradb/trx/trx0roll.cc @@ -492,7 +492,7 @@ trx_release_savepoint_for_mysql( { trx_named_savept_t* savep; - ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE)); + ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE) || trx_state_eq(trx, TRX_STATE_PREPARED)); ut_ad(trx->in_mysql_trx_list); savep = trx_savepoint_find(trx, savepoint_name);