summaryrefslogtreecommitdiffstats
path: root/mysql-test/suite/storage_engine/trx
diff options
context:
space:
mode:
Diffstat (limited to 'mysql-test/suite/storage_engine/trx')
-rw-r--r--mysql-test/suite/storage_engine/trx/cons_snapshot_repeatable_read.result18
-rw-r--r--mysql-test/suite/storage_engine/trx/cons_snapshot_repeatable_read.test9
-rw-r--r--mysql-test/suite/storage_engine/trx/cons_snapshot_serializable.result18
-rw-r--r--mysql-test/suite/storage_engine/trx/cons_snapshot_serializable.test9
-rw-r--r--mysql-test/suite/storage_engine/trx/consistent_snapshot.inc48
-rw-r--r--mysql-test/suite/storage_engine/trx/delete.result72
-rw-r--r--mysql-test/suite/storage_engine/trx/delete.test51
-rw-r--r--mysql-test/suite/storage_engine/trx/insert.result55
-rw-r--r--mysql-test/suite/storage_engine/trx/insert.test44
-rw-r--r--mysql-test/suite/storage_engine/trx/level_read_committed.result91
-rw-r--r--mysql-test/suite/storage_engine/trx/level_read_committed.test10
-rw-r--r--mysql-test/suite/storage_engine/trx/level_read_uncommitted.result116
-rw-r--r--mysql-test/suite/storage_engine/trx/level_read_uncommitted.test9
-rw-r--r--mysql-test/suite/storage_engine/trx/level_repeatable_read.result69
-rw-r--r--mysql-test/suite/storage_engine/trx/level_repeatable_read.test8
-rw-r--r--mysql-test/suite/storage_engine/trx/level_serializable.result56
-rw-r--r--mysql-test/suite/storage_engine/trx/level_serializable.test8
-rw-r--r--mysql-test/suite/storage_engine/trx/my.cnf7
-rw-r--r--mysql-test/suite/storage_engine/trx/select_for_update.result35
-rw-r--r--mysql-test/suite/storage_engine/trx/select_for_update.test85
-rw-r--r--mysql-test/suite/storage_engine/trx/select_lock_in_share_mode.result37
-rw-r--r--mysql-test/suite/storage_engine/trx/select_lock_in_share_mode.test80
-rw-r--r--mysql-test/suite/storage_engine/trx/support_savepoints.inc10
-rw-r--r--mysql-test/suite/storage_engine/trx/support_transactions.inc10
-rw-r--r--mysql-test/suite/storage_engine/trx/support_xa.inc12
-rw-r--r--mysql-test/suite/storage_engine/trx/transaction_isolation.inc97
-rw-r--r--mysql-test/suite/storage_engine/trx/update.result48
-rw-r--r--mysql-test/suite/storage_engine/trx/update.test50
-rw-r--r--mysql-test/suite/storage_engine/trx/xa.result96
-rw-r--r--mysql-test/suite/storage_engine/trx/xa.test116
-rw-r--r--mysql-test/suite/storage_engine/trx/xa_recovery.result29
-rw-r--r--mysql-test/suite/storage_engine/trx/xa_recovery.test74
32 files changed, 1477 insertions, 0 deletions
diff --git a/mysql-test/suite/storage_engine/trx/cons_snapshot_repeatable_read.result b/mysql-test/suite/storage_engine/trx/cons_snapshot_repeatable_read.result
new file mode 100644
index 00000000..3b0bdb3b
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/cons_snapshot_repeatable_read.result
@@ -0,0 +1,18 @@
+DROP TABLE IF EXISTS t1;
+connect con1,localhost,root,,;
+connect con2,localhost,root,,;
+connection con1;
+CREATE TABLE t1 (a <INT_COLUMN>) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+START TRANSACTION WITH CONSISTENT SNAPSHOT;
+connection con2;
+INSERT INTO t1 (a) VALUES (1);
+connection con1;
+# If consistent read works on this isolation level (REPEATABLE READ), the following SELECT should not return the value we inserted (1)
+SELECT a FROM t1;
+a
+COMMIT;
+connection default;
+disconnect con1;
+disconnect con2;
+DROP TABLE t1;
diff --git a/mysql-test/suite/storage_engine/trx/cons_snapshot_repeatable_read.test b/mysql-test/suite/storage_engine/trx/cons_snapshot_repeatable_read.test
new file mode 100644
index 00000000..e44e260e
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/cons_snapshot_repeatable_read.test
@@ -0,0 +1,9 @@
+--source ../have_engine.inc
+--source support_transactions.inc
+
+let $trx_isolation = REPEATABLE READ;
+
+--source consistent_snapshot.inc
+
+--source ../cleanup_engine.inc
+
diff --git a/mysql-test/suite/storage_engine/trx/cons_snapshot_serializable.result b/mysql-test/suite/storage_engine/trx/cons_snapshot_serializable.result
new file mode 100644
index 00000000..691039e8
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/cons_snapshot_serializable.result
@@ -0,0 +1,18 @@
+DROP TABLE IF EXISTS t1;
+connect con1,localhost,root,,;
+connect con2,localhost,root,,;
+connection con1;
+CREATE TABLE t1 (a <INT_COLUMN>) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+START TRANSACTION WITH CONSISTENT SNAPSHOT;
+connection con2;
+INSERT INTO t1 (a) VALUES (1);
+connection con1;
+# If consistent read works on this isolation level (SERIALIZABLE), the following SELECT should not return the value we inserted (1)
+SELECT a FROM t1;
+a
+COMMIT;
+connection default;
+disconnect con1;
+disconnect con2;
+DROP TABLE t1;
diff --git a/mysql-test/suite/storage_engine/trx/cons_snapshot_serializable.test b/mysql-test/suite/storage_engine/trx/cons_snapshot_serializable.test
new file mode 100644
index 00000000..9d516066
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/cons_snapshot_serializable.test
@@ -0,0 +1,9 @@
+--source ../have_engine.inc
+--source support_transactions.inc
+
+let $trx_isolation = SERIALIZABLE;
+
+--source consistent_snapshot.inc
+
+--source ../cleanup_engine.inc
+
diff --git a/mysql-test/suite/storage_engine/trx/consistent_snapshot.inc b/mysql-test/suite/storage_engine/trx/consistent_snapshot.inc
new file mode 100644
index 00000000..cbc1f063
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/consistent_snapshot.inc
@@ -0,0 +1,48 @@
+#
+# TRANSACTION WITH CONSISTENT SNAPSHOT
+#
+
+--source ../have_engine.inc
+
+# Save the initial number of concurrent sessions
+--source include/count_sessions.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+connect (con1,localhost,root,,);
+connect (con2,localhost,root,,);
+
+connection con1;
+
+let $create_definition = a $int_col;
+--source ../create_table.inc
+
+eval SET SESSION TRANSACTION ISOLATION LEVEL $trx_isolation;
+
+# While a consistent snapshot transaction is executed,
+# no external inserts should be visible to the transaction.
+# But it should only work this way for REPEATABLE-READ and SERIALIZABLE
+
+START TRANSACTION WITH CONSISTENT SNAPSHOT;
+
+connection con2;
+INSERT INTO t1 (a) VALUES (1);
+if ($mysql_errname)
+{
+ --echo # INSERT finished with error $mysql_errname
+}
+
+connection con1;
+--echo # If consistent read works on this isolation level ($trx_isolation), the following SELECT should not return the value we inserted (1)
+SELECT a FROM t1;
+COMMIT;
+
+connection default;
+disconnect con1;
+disconnect con2;
+DROP TABLE t1;
+
+--source include/wait_until_count_sessions.inc
+
diff --git a/mysql-test/suite/storage_engine/trx/delete.result b/mysql-test/suite/storage_engine/trx/delete.result
new file mode 100644
index 00000000..14e5389d
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/delete.result
@@ -0,0 +1,72 @@
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a <INT_COLUMN>, b <CHAR_COLUMN>) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+INSERT INTO t1 (a,b) VALUES (1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e'),(6,'f'),(7,'g'),(8,'h'),(10000,'foobar');
+INSERT INTO t1 (a,b) SELECT a, b FROM t1;
+BEGIN;
+DELETE FROM t1 WHERE b IN ('c');
+SELECT a,b FROM t1;
+a b
+1 a
+1 a
+10000 foobar
+10000 foobar
+2 b
+2 b
+4 d
+4 d
+5 e
+5 e
+6 f
+6 f
+7 g
+7 g
+8 h
+8 h
+DELETE FROM t1 WHERE a < 0 OR b = 'a';
+COMMIT;
+SELECT a,b FROM t1;
+a b
+10000 foobar
+10000 foobar
+2 b
+2 b
+4 d
+4 d
+5 e
+5 e
+6 f
+6 f
+7 g
+7 g
+8 h
+8 h
+BEGIN;
+DELETE FROM t1 WHERE a <= 4 ORDER BY b DESC LIMIT 1;
+SAVEPOINT spt1;
+DELETE FROM t1;
+RELEASE SAVEPOINT spt1;
+ROLLBACK;
+SELECT a,b FROM t1;
+a b
+10000 foobar
+10000 foobar
+2 b
+2 b
+4 d
+4 d
+5 e
+5 e
+6 f
+6 f
+7 g
+7 g
+8 h
+8 h
+BEGIN;
+DELETE FROM t1 WHERE a <= 4 ORDER BY b DESC LIMIT 1;
+SAVEPOINT spt1;
+DELETE FROM t1;
+INSERT INTO t1 (a,b) VALUES (1,'a');
+ROLLBACK TO SAVEPOINT spt1;
+COMMIT;
+DROP TABLE t1;
diff --git a/mysql-test/suite/storage_engine/trx/delete.test b/mysql-test/suite/storage_engine/trx/delete.test
new file mode 100644
index 00000000..50da1f20
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/delete.test
@@ -0,0 +1,51 @@
+#
+# Transactional DELETE
+#
+
+--source ../have_engine.inc
+--source support_transactions.inc
+--source support_savepoints.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+--source ../create_table.inc
+INSERT INTO t1 (a,b) VALUES (1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e'),(6,'f'),(7,'g'),(8,'h'),(10000,'foobar');
+INSERT INTO t1 (a,b) SELECT a, b FROM t1;
+
+BEGIN;
+DELETE FROM t1 WHERE b IN ('c');
+if ($mysql_errname)
+{
+ --let $functionality = DELETE
+ --source ../unexpected_result.inc
+}
+--sorted_result
+SELECT a,b FROM t1;
+DELETE FROM t1 WHERE a < 0 OR b = 'a';
+COMMIT;
+--sorted_result
+SELECT a,b FROM t1;
+
+BEGIN;
+DELETE FROM t1 WHERE a <= 4 ORDER BY b DESC LIMIT 1;
+SAVEPOINT spt1;
+DELETE FROM t1;
+RELEASE SAVEPOINT spt1;
+ROLLBACK;
+--sorted_result
+SELECT a,b FROM t1;
+
+BEGIN;
+DELETE FROM t1 WHERE a <= 4 ORDER BY b DESC LIMIT 1;
+SAVEPOINT spt1;
+DELETE FROM t1;
+INSERT INTO t1 (a,b) VALUES (1,'a');
+ROLLBACK TO SAVEPOINT spt1;
+COMMIT;
+
+DROP TABLE t1;
+
+--source ../cleanup_engine.inc
+
diff --git a/mysql-test/suite/storage_engine/trx/insert.result b/mysql-test/suite/storage_engine/trx/insert.result
new file mode 100644
index 00000000..1d8aca98
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/insert.result
@@ -0,0 +1,55 @@
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a <INT_COLUMN>, b <CHAR_COLUMN>) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+BEGIN;
+INSERT INTO t1 (a,b) VALUES (1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e'),(100,'foo');
+INSERT t1 (a,b) VALUE (10,'foo'),(11,'abc');
+COMMIT;
+SELECT a,b FROM t1;
+a b
+1 a
+10 foo
+100 foo
+11 abc
+2 b
+3 c
+4 d
+5 e
+BEGIN;
+INSERT INTO t1 (b,a) VALUES ('test',0);
+SAVEPOINT spt1;
+INSERT INTO t1 (a,b) VALUES (DEFAULT,DEFAULT);
+RELEASE SAVEPOINT spt1;
+INSERT INTO t1 (a,b) VALUES (DEFAULT,DEFAULT);
+ROLLBACK;
+SELECT a,b FROM t1;
+a b
+1 a
+10 foo
+100 foo
+11 abc
+2 b
+3 c
+4 d
+5 e
+BEGIN;
+INSERT t1 (a) VALUE (10),(20);
+SAVEPOINT spt1;
+INSERT INTO t1 SET a = 11, b = 'f';
+INSERT t1 SET b = DEFAULT;
+ROLLBACK TO SAVEPOINT spt1;
+INSERT INTO t1 (b,a) VALUES ('test1',10);
+COMMIT;
+SELECT a,b FROM t1;
+a b
+1 a
+10 NULL
+10 foo
+10 test1
+100 foo
+11 abc
+2 b
+20 NULL
+3 c
+4 d
+5 e
+DROP TABLE t1;
diff --git a/mysql-test/suite/storage_engine/trx/insert.test b/mysql-test/suite/storage_engine/trx/insert.test
new file mode 100644
index 00000000..1a736584
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/insert.test
@@ -0,0 +1,44 @@
+#
+# Transactional INSERT
+#
+--source ../have_engine.inc
+--source support_transactions.inc
+--source support_savepoints.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+--source ../create_table.inc
+BEGIN;
+INSERT INTO t1 (a,b) VALUES (1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e'),(100,'foo');
+INSERT t1 (a,b) VALUE (10,'foo'),(11,'abc');
+COMMIT;
+--sorted_result
+SELECT a,b FROM t1;
+
+BEGIN;
+INSERT INTO t1 (b,a) VALUES ('test',0);
+SAVEPOINT spt1;
+INSERT INTO t1 (a,b) VALUES (DEFAULT,DEFAULT);
+RELEASE SAVEPOINT spt1;
+INSERT INTO t1 (a,b) VALUES (DEFAULT,DEFAULT);
+ROLLBACK;
+--sorted_result
+SELECT a,b FROM t1;
+
+BEGIN;
+INSERT t1 (a) VALUE (10),(20);
+SAVEPOINT spt1;
+INSERT INTO t1 SET a = 11, b = 'f';
+INSERT t1 SET b = DEFAULT;
+ROLLBACK TO SAVEPOINT spt1;
+INSERT INTO t1 (b,a) VALUES ('test1',10);
+COMMIT;
+--sorted_result
+SELECT a,b FROM t1;
+
+DROP TABLE t1;
+
+--source ../cleanup_engine.inc
+
diff --git a/mysql-test/suite/storage_engine/trx/level_read_committed.result b/mysql-test/suite/storage_engine/trx/level_read_committed.result
new file mode 100644
index 00000000..ce1b126d
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/level_read_committed.result
@@ -0,0 +1,91 @@
+DROP TABLE IF EXISTS t1;
+connect con1,localhost,root,,;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+connect con2,localhost,root,,;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+connection con1;
+CREATE TABLE t1 (a <INT_COLUMN>) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+START TRANSACTION;
+SELECT a FROM t1;
+a
+connection con2;
+BEGIN;
+INSERT INTO t1 (a) VALUES(1);
+# WARNING: Statement ended with errno 0, errname ''.
+# If it differs from the result file, it might indicate a problem.
+connection con1;
+SELECT a FROM t1;
+a
+connection con2;
+INSERT INTO t1 (a) VALUES (2);
+# WARNING: Statement ended with errno 0, errname ''.
+# If it differs from the result file, it might indicate a problem.
+connection con1;
+SELECT a FROM t1;
+a
+INSERT INTO t1 (a) SELECT a+100 FROM t1;
+# WARNING: Statement ended with errno 0, errname ''.
+# If it differs from the result file, it might indicate a problem.
+SELECT a FROM t1;
+a
+connection con2;
+SELECT a FROM t1;
+a
+1
+2
+COMMIT;
+SELECT a FROM t1;
+a
+1
+2
+connection con1;
+SELECT a FROM t1;
+a
+1
+2
+INSERT INTO t1 (a) SELECT a+200 FROM t1;
+# WARNING: Statement ended with errno 0, errname ''.
+# If it differs from the result file, it might indicate a problem.
+SELECT a FROM t1;
+a
+1
+2
+201
+202
+COMMIT;
+SELECT a FROM t1;
+a
+1
+2
+201
+202
+connection con2;
+SELECT a FROM t1;
+a
+1
+2
+201
+202
+connection default;
+disconnect con1;
+disconnect con2;
+DROP TABLE t1;
+DROP TABLE IF EXISTS t1;
+connect con1,localhost,root,,;
+connect con2,localhost,root,,;
+connection con1;
+CREATE TABLE t1 (a <INT_COLUMN>) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+START TRANSACTION WITH CONSISTENT SNAPSHOT;
+connection con2;
+INSERT INTO t1 (a) VALUES (1);
+connection con1;
+# If consistent read works on this isolation level (READ COMMITTED), the following SELECT should not return the value we inserted (1)
+SELECT a FROM t1;
+a
+1
+COMMIT;
+connection default;
+disconnect con1;
+disconnect con2;
+DROP TABLE t1;
diff --git a/mysql-test/suite/storage_engine/trx/level_read_committed.test b/mysql-test/suite/storage_engine/trx/level_read_committed.test
new file mode 100644
index 00000000..77bd562c
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/level_read_committed.test
@@ -0,0 +1,10 @@
+--source ../have_engine.inc
+--source support_transactions.inc
+
+let $trx_isolation = READ COMMITTED;
+
+--source transaction_isolation.inc
+--source consistent_snapshot.inc
+
+--source ../cleanup_engine.inc
+
diff --git a/mysql-test/suite/storage_engine/trx/level_read_uncommitted.result b/mysql-test/suite/storage_engine/trx/level_read_uncommitted.result
new file mode 100644
index 00000000..68fbe563
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/level_read_uncommitted.result
@@ -0,0 +1,116 @@
+DROP TABLE IF EXISTS t1;
+connect con1,localhost,root,,;
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+connect con2,localhost,root,,;
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+connection con1;
+CREATE TABLE t1 (a <INT_COLUMN>) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+START TRANSACTION;
+SELECT a FROM t1;
+a
+connection con2;
+BEGIN;
+INSERT INTO t1 (a) VALUES(1);
+# WARNING: Statement ended with errno 0, errname ''.
+# If it differs from the result file, it might indicate a problem.
+connection con1;
+SELECT a FROM t1;
+a
+1
+connection con2;
+INSERT INTO t1 (a) VALUES (2);
+# WARNING: Statement ended with errno 0, errname ''.
+# If it differs from the result file, it might indicate a problem.
+connection con1;
+SELECT a FROM t1;
+a
+1
+2
+INSERT INTO t1 (a) SELECT a+100 FROM t1;
+# WARNING: Statement ended with errno 0, errname ''.
+# If it differs from the result file, it might indicate a problem.
+SELECT a FROM t1;
+a
+1
+101
+102
+2
+connection con2;
+SELECT a FROM t1;
+a
+1
+101
+102
+2
+COMMIT;
+SELECT a FROM t1;
+a
+1
+101
+102
+2
+connection con1;
+SELECT a FROM t1;
+a
+1
+101
+102
+2
+INSERT INTO t1 (a) SELECT a+200 FROM t1;
+# WARNING: Statement ended with errno 0, errname ''.
+# If it differs from the result file, it might indicate a problem.
+SELECT a FROM t1;
+a
+1
+101
+102
+2
+201
+202
+301
+302
+COMMIT;
+SELECT a FROM t1;
+a
+1
+101
+102
+2
+201
+202
+301
+302
+connection con2;
+SELECT a FROM t1;
+a
+1
+101
+102
+2
+201
+202
+301
+302
+connection default;
+disconnect con1;
+disconnect con2;
+DROP TABLE t1;
+DROP TABLE IF EXISTS t1;
+connect con1,localhost,root,,;
+connect con2,localhost,root,,;
+connection con1;
+CREATE TABLE t1 (a <INT_COLUMN>) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+START TRANSACTION WITH CONSISTENT SNAPSHOT;
+connection con2;
+INSERT INTO t1 (a) VALUES (1);
+connection con1;
+# If consistent read works on this isolation level (READ UNCOMMITTED), the following SELECT should not return the value we inserted (1)
+SELECT a FROM t1;
+a
+1
+COMMIT;
+connection default;
+disconnect con1;
+disconnect con2;
+DROP TABLE t1;
diff --git a/mysql-test/suite/storage_engine/trx/level_read_uncommitted.test b/mysql-test/suite/storage_engine/trx/level_read_uncommitted.test
new file mode 100644
index 00000000..48310fc2
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/level_read_uncommitted.test
@@ -0,0 +1,9 @@
+--source ../have_engine.inc
+--source support_transactions.inc
+
+let $trx_isolation = READ UNCOMMITTED;
+--source transaction_isolation.inc
+--source consistent_snapshot.inc
+
+--source ../cleanup_engine.inc
+
diff --git a/mysql-test/suite/storage_engine/trx/level_repeatable_read.result b/mysql-test/suite/storage_engine/trx/level_repeatable_read.result
new file mode 100644
index 00000000..c828b18d
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/level_repeatable_read.result
@@ -0,0 +1,69 @@
+DROP TABLE IF EXISTS t1;
+connect con1,localhost,root,,;
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+connect con2,localhost,root,,;
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+connection con1;
+CREATE TABLE t1 (a <INT_COLUMN>) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+START TRANSACTION;
+SELECT a FROM t1;
+a
+connection con2;
+BEGIN;
+INSERT INTO t1 (a) VALUES(1);
+# WARNING: Statement ended with errno 0, errname ''.
+# If it differs from the result file, it might indicate a problem.
+connection con1;
+SELECT a FROM t1;
+a
+connection con2;
+INSERT INTO t1 (a) VALUES (2);
+# WARNING: Statement ended with errno 0, errname ''.
+# If it differs from the result file, it might indicate a problem.
+connection con1;
+SELECT a FROM t1;
+a
+INSERT INTO t1 (a) SELECT a+100 FROM t1;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+# WARNING: Statement ended with errno 1205, errname 'ER_LOCK_WAIT_TIMEOUT'.
+# If it differs from the result file, it might indicate a problem.
+SELECT a FROM t1;
+a
+connection con2;
+SELECT a FROM t1;
+a
+1
+2
+COMMIT;
+SELECT a FROM t1;
+a
+1
+2
+connection con1;
+SELECT a FROM t1;
+a
+INSERT INTO t1 (a) SELECT a+200 FROM t1;
+# WARNING: Statement ended with errno 0, errname ''.
+# If it differs from the result file, it might indicate a problem.
+SELECT a FROM t1;
+a
+201
+202
+COMMIT;
+SELECT a FROM t1;
+a
+1
+2
+201
+202
+connection con2;
+SELECT a FROM t1;
+a
+1
+2
+201
+202
+connection default;
+disconnect con1;
+disconnect con2;
+DROP TABLE t1;
diff --git a/mysql-test/suite/storage_engine/trx/level_repeatable_read.test b/mysql-test/suite/storage_engine/trx/level_repeatable_read.test
new file mode 100644
index 00000000..cb33d109
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/level_repeatable_read.test
@@ -0,0 +1,8 @@
+--source ../have_engine.inc
+--source support_transactions.inc
+
+let $trx_isolation = REPEATABLE READ;
+--source transaction_isolation.inc
+
+--source ../cleanup_engine.inc
+
diff --git a/mysql-test/suite/storage_engine/trx/level_serializable.result b/mysql-test/suite/storage_engine/trx/level_serializable.result
new file mode 100644
index 00000000..3f57395f
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/level_serializable.result
@@ -0,0 +1,56 @@
+DROP TABLE IF EXISTS t1;
+connect con1,localhost,root,,;
+SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+connect con2,localhost,root,,;
+SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+connection con1;
+CREATE TABLE t1 (a <INT_COLUMN>) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+START TRANSACTION;
+SELECT a FROM t1;
+a
+connection con2;
+BEGIN;
+INSERT INTO t1 (a) VALUES(1);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+# WARNING: Statement ended with errno 1205, errname 'ER_LOCK_WAIT_TIMEOUT'.
+# If it differs from the result file, it might indicate a problem.
+connection con1;
+SELECT a FROM t1;
+a
+connection con2;
+INSERT INTO t1 (a) VALUES (2);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+# WARNING: Statement ended with errno 1205, errname 'ER_LOCK_WAIT_TIMEOUT'.
+# If it differs from the result file, it might indicate a problem.
+connection con1;
+SELECT a FROM t1;
+a
+INSERT INTO t1 (a) SELECT a+100 FROM t1;
+# WARNING: Statement ended with errno 0, errname ''.
+# If it differs from the result file, it might indicate a problem.
+SELECT a FROM t1;
+a
+connection con2;
+SELECT a FROM t1;
+a
+COMMIT;
+SELECT a FROM t1;
+a
+connection con1;
+SELECT a FROM t1;
+a
+INSERT INTO t1 (a) SELECT a+200 FROM t1;
+# WARNING: Statement ended with errno 0, errname ''.
+# If it differs from the result file, it might indicate a problem.
+SELECT a FROM t1;
+a
+COMMIT;
+SELECT a FROM t1;
+a
+connection con2;
+SELECT a FROM t1;
+a
+connection default;
+disconnect con1;
+disconnect con2;
+DROP TABLE t1;
diff --git a/mysql-test/suite/storage_engine/trx/level_serializable.test b/mysql-test/suite/storage_engine/trx/level_serializable.test
new file mode 100644
index 00000000..4372b489
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/level_serializable.test
@@ -0,0 +1,8 @@
+--source ../have_engine.inc
+--source support_transactions.inc
+
+let $trx_isolation = SERIALIZABLE;
+--source transaction_isolation.inc
+
+--source ../cleanup_engine.inc
+
diff --git a/mysql-test/suite/storage_engine/trx/my.cnf b/mysql-test/suite/storage_engine/trx/my.cnf
new file mode 100644
index 00000000..e83954c4
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/my.cnf
@@ -0,0 +1,7 @@
+!include include/default_my.cnf
+
+[server]
+sql-mode=NO_ENGINE_SUBSTITUTION
+binlog-format=row
+log-bin=master-bin
+
diff --git a/mysql-test/suite/storage_engine/trx/select_for_update.result b/mysql-test/suite/storage_engine/trx/select_for_update.result
new file mode 100644
index 00000000..f5954489
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/select_for_update.result
@@ -0,0 +1,35 @@
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a <INT_COLUMN>, b <CHAR_COLUMN>) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+INSERT INTO t1 (a,b) VALUES (1,'a'),(2,'b'),(3,'a');
+connect con1,localhost,root,,;
+BEGIN;
+SELECT a,b FROM t1 WHERE b='a' FOR UPDATE;
+a b
+1 a
+3 a
+connection default;
+SET lock_wait_timeout = 1;
+SELECT a,b FROM t1 WHERE b='a';
+a b
+1 a
+3 a
+SELECT a,b FROM t1 WHERE b='a' LOCK IN SHARE MODE;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+UPDATE t1 SET b='c' WHERE b='a';
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+connection con1;
+COMMIT;
+SELECT a,b FROM t1;
+a b
+1 a
+2 b
+3 a
+disconnect con1;
+connection default;
+UPDATE t1 SET b='c' WHERE b='a';
+SELECT a,b FROM t1;
+a b
+1 c
+2 b
+3 c
+DROP TABLE t1;
diff --git a/mysql-test/suite/storage_engine/trx/select_for_update.test b/mysql-test/suite/storage_engine/trx/select_for_update.test
new file mode 100644
index 00000000..0e5a3eee
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/select_for_update.test
@@ -0,0 +1,85 @@
+#
+# SELECT .. FOR UPDATE
+#
+# If the engine has its own lock timeouts,
+# it makes sense to set them to minimum to decrease
+# the duration of the test.
+
+--source ../have_engine.inc
+--source support_transactions.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+--source include/count_sessions.inc
+
+--source ../create_table.inc
+INSERT INTO t1 (a,b) VALUES (1,'a'),(2,'b'),(3,'a');
+
+--connect (con1,localhost,root,,)
+BEGIN;
+--sorted_result
+SELECT a,b FROM t1 WHERE b='a' FOR UPDATE;
+if ($mysql_errname)
+{
+ --let $functionality = SELECT .. FOR UPDATE
+ --source ../unexpected_result.inc
+}
+
+--connection default
+SET lock_wait_timeout = 1;
+
+# Should still be able to select
+
+--sorted_result
+SELECT a,b FROM t1 WHERE b='a';
+if ($mysql_errname)
+{
+ --let $functionality = SELECT .. FOR UPDATE or locking
+ --source ../unexpected_result.inc
+}
+
+# ... but not with LOCK IN SHARE MODE
+
+--sorted_result
+--let $error_codes = ER_LOCK_WAIT_TIMEOUT
+SELECT a,b FROM t1 WHERE b='a' LOCK IN SHARE MODE;
+--source ../check_errors.inc
+if ($mysql_errname != ER_LOCK_WAIT_TIMEOUT)
+{
+ --let $functionality = SELECT .. FOR UPDATE or LOCK IN SHARE MODE
+ --source ../unexpected_result.inc
+}
+
+--let $error_codes = ER_LOCK_WAIT_TIMEOUT
+UPDATE t1 SET b='c' WHERE b='a';
+--source ../check_errors.inc
+if ($mysql_errname != ER_LOCK_WAIT_TIMEOUT)
+{
+ --let $functionality = UPDATE or SELECT .. FOR UPDATE
+ --source ../unexpected_result.inc
+}
+
+--connection con1
+COMMIT;
+--sorted_result
+SELECT a,b FROM t1;
+
+--disconnect con1
+--connection default
+# Now it can be updated all right
+UPDATE t1 SET b='c' WHERE b='a';
+if ($mysql_errname)
+{
+ --let $functionality = UPDATE
+ --source ../unexpected_result.inc
+}
+--sorted_result
+SELECT a,b FROM t1;
+
+DROP TABLE t1;
+
+--source include/wait_until_count_sessions.inc
+--source ../cleanup_engine.inc
+
diff --git a/mysql-test/suite/storage_engine/trx/select_lock_in_share_mode.result b/mysql-test/suite/storage_engine/trx/select_lock_in_share_mode.result
new file mode 100644
index 00000000..3d668d72
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/select_lock_in_share_mode.result
@@ -0,0 +1,37 @@
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a <INT_COLUMN>, b <CHAR_COLUMN>) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+INSERT INTO t1 (a,b) VALUES (1,'a'),(2,'b'),(3,'a');
+connect con1,localhost,root,,;
+BEGIN;
+SELECT a,b FROM t1 WHERE b='a' LOCK IN SHARE MODE;
+a b
+1 a
+3 a
+connection default;
+SET lock_wait_timeout = 1;
+SELECT a,b FROM t1 WHERE b='a';
+a b
+1 a
+3 a
+SELECT a,b FROM t1 WHERE b='a' LOCK IN SHARE MODE;
+a b
+1 a
+3 a
+UPDATE t1 SET b='c' WHERE b='a';
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+connection con1;
+COMMIT;
+SELECT a,b FROM t1;
+a b
+1 a
+2 b
+3 a
+disconnect con1;
+connection default;
+UPDATE t1 SET b='c' WHERE b='a';
+SELECT a,b FROM t1;
+a b
+1 c
+2 b
+3 c
+DROP TABLE t1;
diff --git a/mysql-test/suite/storage_engine/trx/select_lock_in_share_mode.test b/mysql-test/suite/storage_engine/trx/select_lock_in_share_mode.test
new file mode 100644
index 00000000..92061036
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/select_lock_in_share_mode.test
@@ -0,0 +1,80 @@
+#
+# SELECT .. LOCK IN SHARE MODE
+#
+# If the engine has its own lock timeouts,
+# it makes sense to set them to minimum to decrease
+# the duration of the test.
+
+--source ../have_engine.inc
+--source support_transactions.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+--source include/count_sessions.inc
+
+--source ../create_table.inc
+INSERT INTO t1 (a,b) VALUES (1,'a'),(2,'b'),(3,'a');
+
+--connect (con1,localhost,root,,)
+BEGIN;
+--sorted_result
+SELECT a,b FROM t1 WHERE b='a' LOCK IN SHARE MODE;
+if ($mysql_errname)
+{
+ --let $functionality = LOCK IN SHARE MODE
+ --source ../unexpected_result.inc
+}
+
+--connection default
+SET lock_wait_timeout = 1;
+
+# Should still be able to select
+
+--sorted_result
+SELECT a,b FROM t1 WHERE b='a';
+if ($mysql_errname)
+{
+ --let $functionality = LOCK IN SHARE MODE
+ --source ../unexpected_result.inc
+}
+--sorted_result
+SELECT a,b FROM t1 WHERE b='a' LOCK IN SHARE MODE;
+if ($mysql_errname)
+{
+ --let $functionality = LOCK IN SHARE MODE
+ --source ../unexpected_result.inc
+}
+
+--let $error_codes = ER_LOCK_WAIT_TIMEOUT
+UPDATE t1 SET b='c' WHERE b='a';
+--source ../check_errors.inc
+if ($mysql_errname != ER_LOCK_WAIT_TIMEOUT)
+{
+ --let $functionality = LOCK IN SHARE MODE or UPDATE
+ --source ../unexpected_result.inc
+}
+
+--connection con1
+COMMIT;
+--sorted_result
+SELECT a,b FROM t1;
+
+--disconnect con1
+--connection default
+# Now it can be updated all right
+UPDATE t1 SET b='c' WHERE b='a';
+if ($mysql_errname)
+{
+ --let $functionality = UPDATE
+ --source ../unexpected_result.inc
+}
+--sorted_result
+SELECT a,b FROM t1;
+
+DROP TABLE t1;
+
+--source include/wait_until_count_sessions.inc
+--source ../cleanup_engine.inc
+
diff --git a/mysql-test/suite/storage_engine/trx/support_savepoints.inc b/mysql-test/suite/storage_engine/trx/support_savepoints.inc
new file mode 100644
index 00000000..36dbfce2
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/support_savepoints.inc
@@ -0,0 +1,10 @@
+if (!`SELECT savepoints='YES' FROM INFORMATION_SCHEMA.ENGINES WHERE engine = '$storage_engine'`)
+{
+ --echo # -- WARNING ----------------------------------------------------------------
+ --echo # According to I_S.ENGINES, $storage_engine does not support savepoints.
+ --echo # If it is true, the test will most likely fail; you can
+ --echo # either create an rdiff file (recommended), or add the test to disabled.def.
+ --echo # If savepoints should be supported, check the data in Information Schema.
+ --echo # ---------------------------------------------------------------------------
+}
+
diff --git a/mysql-test/suite/storage_engine/trx/support_transactions.inc b/mysql-test/suite/storage_engine/trx/support_transactions.inc
new file mode 100644
index 00000000..ff1224c5
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/support_transactions.inc
@@ -0,0 +1,10 @@
+if (!`SELECT transactions='YES' FROM INFORMATION_SCHEMA.ENGINES WHERE engine = '$storage_engine'`)
+{
+ --echo # -- WARNING ----------------------------------------------------------------
+ --echo # According to I_S.ENGINES, $storage_engine does not support transactions.
+ --echo # If it is true, the test will most likely fail; you can
+ --echo # either create an rdiff file, or add the test to disabled.def.
+ --echo # If transactions should be supported, check the data in Information Schema.
+ --echo # ---------------------------------------------------------------------------
+}
+
diff --git a/mysql-test/suite/storage_engine/trx/support_xa.inc b/mysql-test/suite/storage_engine/trx/support_xa.inc
new file mode 100644
index 00000000..d51fc48a
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/support_xa.inc
@@ -0,0 +1,12 @@
+--let $support_xa = 1
+if (!`SELECT xa='YES' FROM INFORMATION_SCHEMA.ENGINES WHERE engine = '$storage_engine'`)
+{
+ --echo # -- WARNING ----------------------------------------------------------------
+ --echo # According to I_S.ENGINES, $storage_engine does not support XA.
+ --echo # If it is true, the test will most likely fail; you can
+ --echo # either create an rdiff file, or add the test to disabled.def.
+ --echo # If XA should be supported, check the data in Information Schema.
+ --echo # ---------------------------------------------------------------------------
+ --let $support_xa = 0
+}
+
diff --git a/mysql-test/suite/storage_engine/trx/transaction_isolation.inc b/mysql-test/suite/storage_engine/trx/transaction_isolation.inc
new file mode 100644
index 00000000..3ff214bd
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/transaction_isolation.inc
@@ -0,0 +1,97 @@
+#
+# Basic check for transaction isolation.
+# The results should be different depending on the isolation level.
+# For some isolation levels, some statements will end with a timeout.
+# If the engine has its own timeout parameters, reduce them to minimum,
+# otherwise the test will take very long.
+# If the timeout value is greater than the testcase-timeout the test is run with,
+# it might fail due to the testcase timeout.
+#
+
+--source ../have_engine.inc
+
+# Save the initial number of concurrent sessions
+--source include/count_sessions.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+connect (con1,localhost,root,,);
+eval SET SESSION TRANSACTION ISOLATION LEVEL $trx_isolation;
+connect (con2,localhost,root,,);
+eval SET SESSION TRANSACTION ISOLATION LEVEL $trx_isolation;
+
+connection con1;
+
+let $create_definition = a $int_col;
+--source ../create_table.inc
+
+START TRANSACTION;
+--sorted_result
+SELECT a FROM t1; # First snapshot
+
+connection con2;
+
+BEGIN;
+--let $error_codes = 0,ER_LOCK_WAIT_TIMEOUT
+INSERT INTO t1 (a) VALUES(1);
+--source ../strict_check_errors.inc
+
+connection con1;
+--sorted_result
+SELECT a FROM t1; # Second snapshot
+
+connection con2;
+--let $error_codes = 0,ER_LOCK_WAIT_TIMEOUT
+INSERT INTO t1 (a) VALUES (2);
+--source ../strict_check_errors.inc
+
+connection con1;
+--sorted_result
+SELECT a FROM t1; # Third snapshot
+
+--let $error_codes = 0,ER_LOCK_WAIT_TIMEOUT
+INSERT INTO t1 (a) SELECT a+100 FROM t1;
+--source ../strict_check_errors.inc
+
+--sorted_result
+SELECT a FROM t1;
+
+connection con2;
+--sorted_result
+SELECT a FROM t1; # Inside the transaction
+COMMIT;
+--sorted_result
+SELECT a FROM t1; # Outside the transaction
+
+connection con1;
+--sorted_result
+SELECT a FROM t1; # Inside the transaction
+
+# Note: INSERT .. SELECT might be tricky, for example for InnoDB
+# even with REPEATABLE-READ it works as if it is executed with READ COMMITTED.
+# The test will have a 'logical' result for repeatable read, even although
+# we currently don't have an engine which works this way.
+
+--let $error_codes = 0,ER_LOCK_WAIT_TIMEOUT
+INSERT INTO t1 (a) SELECT a+200 FROM t1;
+--source ../strict_check_errors.inc
+
+--sorted_result
+SELECT a FROM t1;
+COMMIT;
+--sorted_result
+SELECT a FROM t1; # Outside the transaction
+
+connection con2;
+--sorted_result
+SELECT a FROM t1; # After both transactions have committed
+
+connection default;
+disconnect con1;
+disconnect con2;
+DROP TABLE t1;
+
+--source include/wait_until_count_sessions.inc
+
diff --git a/mysql-test/suite/storage_engine/trx/update.result b/mysql-test/suite/storage_engine/trx/update.result
new file mode 100644
index 00000000..96867461
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/update.result
@@ -0,0 +1,48 @@
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a <INT_COLUMN>, b <CHAR_COLUMN>) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+INSERT INTO t1 (a,b) VALUES (1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e'),(10000,'foobar');
+INSERT INTO t1 (a,b) SELECT a, b FROM t1;
+BEGIN;
+UPDATE t1 SET a=a+100;
+UPDATE t1 SET a=a-50, b=DEFAULT WHERE a>100;
+COMMIT;
+SELECT a,b FROM t1;
+a b
+10050 NULL
+10050 NULL
+51 NULL
+51 NULL
+52 NULL
+52 NULL
+53 NULL
+53 NULL
+54 NULL
+54 NULL
+55 NULL
+55 NULL
+BEGIN;
+UPDATE t1 SET b = 'update' WHERE a <= 4 ORDER BY a DESC, b ASC LIMIT 3;
+UPDATE t1 SET b = '';
+ROLLBACK;
+BEGIN;
+UPDATE t1 SET b = 'update2' WHERE a <= 100;
+SAVEPOINT spt1;
+UPDATE t1 SET b = '';
+ROLLBACK TO SAVEPOINT spt1;
+UPDATE t1 SET b = 'upd' WHERE a = 10050;
+COMMIT;
+SELECT a,b FROM t1;
+a b
+10050 upd
+10050 upd
+51 update2
+51 update2
+52 update2
+52 update2
+53 update2
+53 update2
+54 update2
+54 update2
+55 update2
+55 update2
+DROP TABLE t1;
diff --git a/mysql-test/suite/storage_engine/trx/update.test b/mysql-test/suite/storage_engine/trx/update.test
new file mode 100644
index 00000000..245b7554
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/update.test
@@ -0,0 +1,50 @@
+#
+# Transactional UPDATE
+#
+
+--source ../have_engine.inc
+--source support_transactions.inc
+--source support_savepoints.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+--source ../create_table.inc
+INSERT INTO t1 (a,b) VALUES (1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e'),(10000,'foobar');
+INSERT INTO t1 (a,b) SELECT a, b FROM t1;
+
+BEGIN;
+UPDATE t1 SET a=a+100;
+if ($mysql_errname)
+{
+ --let $functionality = UPDATE
+ --source ../unexpected_result.inc
+}
+if (!$mysql_errname)
+{
+ UPDATE t1 SET a=a-50, b=DEFAULT WHERE a>100;
+ COMMIT;
+ --sorted_result
+ SELECT a,b FROM t1;
+
+ BEGIN;
+ UPDATE t1 SET b = 'update' WHERE a <= 4 ORDER BY a DESC, b ASC LIMIT 3;
+ UPDATE t1 SET b = '';
+ ROLLBACK;
+
+ BEGIN;
+ UPDATE t1 SET b = 'update2' WHERE a <= 100;
+ SAVEPOINT spt1;
+ UPDATE t1 SET b = '';
+ ROLLBACK TO SAVEPOINT spt1;
+ UPDATE t1 SET b = 'upd' WHERE a = 10050;
+ COMMIT;
+ --sorted_result
+ SELECT a,b FROM t1;
+}
+
+DROP TABLE t1;
+
+--source ../cleanup_engine.inc
+
diff --git a/mysql-test/suite/storage_engine/trx/xa.result b/mysql-test/suite/storage_engine/trx/xa.result
new file mode 100644
index 00000000..72017018
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/xa.result
@@ -0,0 +1,96 @@
+DROP TABLE IF EXISTS t1;
+connect con1,localhost,root,,;
+connect con2,localhost,root,,;
+connection con1;
+CREATE TABLE t1 (a <INT_COLUMN>) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+connection con2;
+XA START 'xa1';
+INSERT INTO t1 (a) VALUES (1);
+connection con1;
+SELECT a FROM t1;
+a
+connection con2;
+INSERT INTO t1 (a) VALUES (2);
+XA END 'xa1';
+connection con1;
+SELECT a FROM t1;
+a
+connection con2;
+XA PREPARE 'xa1';
+connection con1;
+SELECT a FROM t1;
+a
+connection con2;
+XA RECOVER;
+formatID gtrid_length bqual_length data
+1 3 0 xa1
+XA COMMIT 'xa1';
+connection con1;
+SELECT a FROM t1;
+a
+1
+2
+connection con2;
+XA START 'xa2';
+INSERT INTO t1 (a) VALUES (3);
+connection con1;
+SELECT a FROM t1;
+a
+1
+2
+connection con2;
+INSERT INTO t1 (a) VALUES (4);
+XA END 'xa2';
+connection con1;
+SELECT a FROM t1;
+a
+1
+2
+connection con2;
+XA COMMIT 'xa2' ONE PHASE;
+connection con1;
+SELECT a FROM t1;
+a
+1
+2
+3
+4
+connection con2;
+XA START 'xa3';
+INSERT INTO t1 (a) VALUES (5);
+connection con1;
+SELECT a FROM t1;
+a
+1
+2
+3
+4
+connection con2;
+INSERT INTO t1 (a) VALUES (6);
+XA END 'xa3';
+connection con1;
+SELECT a FROM t1;
+a
+1
+2
+3
+4
+connection con2;
+XA PREPARE 'xa3';
+connection con1;
+SELECT a FROM t1;
+a
+1
+2
+3
+4
+connection con2;
+XA ROLLBACK 'xa3';
+connection con1;
+SELECT a FROM t1;
+a
+1
+2
+3
+4
+DROP TABLE t1;
diff --git a/mysql-test/suite/storage_engine/trx/xa.test b/mysql-test/suite/storage_engine/trx/xa.test
new file mode 100644
index 00000000..8dafa802
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/xa.test
@@ -0,0 +1,116 @@
+#
+# Basic XA transactions syntax
+#
+
+--source ../have_engine.inc
+--source support_xa.inc
+
+# Save the initial number of concurrent sessions
+--source include/count_sessions.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+--connect (con1,localhost,root,,)
+--connect (con2,localhost,root,,)
+
+--connection con1
+--let $create_definition = a $int_col
+--source ../create_table.inc
+
+--connection con2
+
+# Two-phase COMMIT
+
+XA START 'xa1';
+INSERT INTO t1 (a) VALUES (1);
+
+--connection con1
+--sorted_result
+SELECT a FROM t1;
+
+--connection con2
+INSERT INTO t1 (a) VALUES (2);
+XA END 'xa1';
+
+--connection con1
+--sorted_result
+SELECT a FROM t1;
+
+--connection con2
+XA PREPARE 'xa1';
+
+--connection con1
+--sorted_result
+SELECT a FROM t1;
+
+--connection con2
+XA RECOVER;
+XA COMMIT 'xa1';
+
+--connection con1
+--sorted_result
+SELECT a FROM t1;
+
+# One-phase COMMIT
+
+--connection con2
+XA START 'xa2';
+INSERT INTO t1 (a) VALUES (3);
+
+--connection con1
+--sorted_result
+SELECT a FROM t1;
+
+--connection con2
+INSERT INTO t1 (a) VALUES (4);
+XA END 'xa2';
+
+--connection con1
+--sorted_result
+SELECT a FROM t1;
+
+--connection con2
+XA COMMIT 'xa2' ONE PHASE;
+
+--connection con1
+--sorted_result
+SELECT a FROM t1;
+
+# Rollback
+
+--connection con2
+XA START 'xa3';
+INSERT INTO t1 (a) VALUES (5);
+
+--connection con1
+--sorted_result
+SELECT a FROM t1;
+
+--connection con2
+INSERT INTO t1 (a) VALUES (6);
+XA END 'xa3';
+
+--connection con1
+--sorted_result
+SELECT a FROM t1;
+
+--connection con2
+XA PREPARE 'xa3';
+
+--connection con1
+--sorted_result
+SELECT a FROM t1;
+
+--connection con2
+XA ROLLBACK 'xa3';
+
+--connection con1
+--sorted_result
+SELECT a FROM t1;
+
+DROP TABLE t1;
+
+--source ../cleanup_engine.inc
+
diff --git a/mysql-test/suite/storage_engine/trx/xa_recovery.result b/mysql-test/suite/storage_engine/trx/xa_recovery.result
new file mode 100644
index 00000000..a9208a6e
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/xa_recovery.result
@@ -0,0 +1,29 @@
+call mtr.add_suppression("Found 2 prepared XA transactions");
+FLUSH TABLES;
+DROP TABLE IF EXISTS t1;
+connect con1,localhost,root,,;
+connect con2,localhost,root,,;
+connection con1;
+CREATE TABLE t1 (a <INT_COLUMN>) ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS>;
+XA START 'xa1';
+INSERT INTO t1 (a) VALUES (1),(2);
+XA END 'xa1';
+XA PREPARE 'xa1';
+connection con2;
+XA START 'xa2';
+INSERT INTO t1 (a) VALUES (3);
+INSERT INTO t1 (a) VALUES (4);
+XA END 'xa2';
+XA PREPARE 'xa2';
+connection default;
+XA RECOVER;
+formatID gtrid_length bqual_length data
+1 3 0 xa1
+1 3 0 xa2
+XA ROLLBACK 'xa1';
+XA COMMIT 'xa2';
+SELECT a FROM t1;
+a
+3
+4
+DROP TABLE t1;
diff --git a/mysql-test/suite/storage_engine/trx/xa_recovery.test b/mysql-test/suite/storage_engine/trx/xa_recovery.test
new file mode 100644
index 00000000..f5364057
--- /dev/null
+++ b/mysql-test/suite/storage_engine/trx/xa_recovery.test
@@ -0,0 +1,74 @@
+#
+# Server restart with uncommitted XA transactions
+#
+
+--source ../have_engine.inc
+--source support_xa.inc
+
+# Before we start, we want to restart the server gracefully,
+# so GCOV information and everything else is properly stored
+
+--enable_reconnect
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart
+EOF
+--shutdown_server
+--source include/wait_until_connected_again.inc
+
+
+call mtr.add_suppression("Found 2 prepared XA transactions");
+if (!$support_xa)
+{
+ --disable_query_log
+ call mtr.add_suppression("Table '.*t1' is marked as crashed and should be repaired");
+ call mtr.add_suppression("Checking table: '.*t1'");
+ --enable_query_log
+}
+
+# Close all unused tables to prevent unrelated corruption
+FLUSH TABLES;
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+--connect (con1,localhost,root,,)
+--connect (con2,localhost,root,,)
+
+--connection con1
+--let $create_definition = a $int_col
+--source ../create_table.inc
+
+XA START 'xa1';
+INSERT INTO t1 (a) VALUES (1),(2);
+XA END 'xa1';
+XA PREPARE 'xa1';
+
+--connection con2
+XA START 'xa2';
+INSERT INTO t1 (a) VALUES (3);
+INSERT INTO t1 (a) VALUES (4);
+XA END 'xa2';
+XA PREPARE 'xa2';
+
+--connection default
+--enable_reconnect
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+wait
+EOF
+--shutdown_server 0
+--source include/wait_until_disconnected.inc
+
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+restart
+EOF
+--source include/wait_until_connected_again.inc
+XA RECOVER;
+XA ROLLBACK 'xa1';
+XA COMMIT 'xa2';
+--replace_result \\ /
+SELECT a FROM t1;
+DROP TABLE t1;
+
+--source ../cleanup_engine.inc
+