diff options
author | Sachin Kumar <sachin.setiya@mariadb.com> | 2021-05-14 08:11:13 +0100 |
---|---|---|
committer | Sachin Kumar <sachin.setiya@mariadb.com> | 2021-06-07 11:14:42 +0100 |
commit | 55c8b426fa8e841b8807f4fecc961e61765d138a (patch) | |
tree | 1eef092a0affbe624fabea97d9953943458523b7 | |
parent | 8d40039fb5a574fc1fd09b1cd7ef3161c9045f08 (diff) | |
download | mariadb-git-tmp_sachin.tar.gz |
Roll Forward recovery for binlog teststmp_sachin
23 files changed, 1007 insertions, 0 deletions
diff --git a/mysql-test/suite/rpl/include/binlog_commit_crash_crud.inc b/mysql-test/suite/rpl/include/binlog_commit_crash_crud.inc new file mode 100644 index 00000000000..d9545a79f0a --- /dev/null +++ b/mysql-test/suite/rpl/include/binlog_commit_crash_crud.inc @@ -0,0 +1,34 @@ +# +# Execute a transaction and crash the server after binlog commit. +# +# @@input $exec_query The query which needs to be executed. + +--connection master +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait +EOF + +SET GLOBAL DEBUG_DBUG="d,simulate_crash_after_binlog_commit_or_rollback"; +--error 2013 # CR_SERVER_LOST +--eval $exec_query + +--source include/wait_until_disconnected.inc + +# Server restart +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart +EOF + +connection default; +--enable_reconnect +--source include/wait_until_connected_again.inc + +# rpl_end.inc needs to use the connection server_1 +connection server_1; +--enable_reconnect +--source include/wait_until_connected_again.inc + +--connection master +--enable_reconnect +--source include/wait_until_connected_again.inc + diff --git a/mysql-test/suite/rpl/r/rpl_binlog_commit_crash_safe.result b/mysql-test/suite/rpl/r/rpl_binlog_commit_crash_safe.result new file mode 100644 index 00000000000..766169caee3 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_binlog_commit_crash_safe.result @@ -0,0 +1,39 @@ +include/master-slave.inc +[connection master] +connection master; +CREATE TABLE t ( f INT) ENGINE=INNODB; +INSERT INTO t values(1); +connection slave; +connection master; +SET GLOBAL DEBUG_DBUG="d,simulate_crash_after_binlog_commit_or_rollback"; +INSERT INTO t values(10); +ERROR HY000: Lost connection to MySQL server during query +connection default; +connection server_1; +connection master; +connection master; +SET GLOBAL DEBUG_DBUG="d,simulate_crash_after_binlog_commit_or_rollback"; +update t set f= 2 where f= 1; +ERROR HY000: Lost connection to MySQL server during query +connection default; +connection server_1; +connection master; +connection master; +SET GLOBAL DEBUG_DBUG="d,simulate_crash_after_binlog_commit_or_rollback"; +delete from t where f= 2; +ERROR HY000: Lost connection to MySQL server during query +connection default; +connection server_1; +connection master; +connection master; +SELECT * FROM t; +f +10 +connection slave; +SELECT * FROM t; +f +10 +connection master; +DROP TABLE t; +connection slave; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_xa_commit_crash_safe_innodb_sync.result b/mysql-test/suite/rpl/r/rpl_xa_commit_crash_safe_innodb_sync.result new file mode 100644 index 00000000000..ce7d257690a --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_xa_commit_crash_safe_innodb_sync.result @@ -0,0 +1,50 @@ +include/master-slave.inc +[connection master] +connect master2,localhost,root,,; +connection master; +CALL mtr.add_suppression("Found 1 prepared XA transactions"); +CREATE TABLE t ( f INT ) ENGINE=INNODB; +XA START 'xa1'; +INSERT INTO t VALUES (20); +XA END 'xa1'; +XA PREPARE 'xa1'; +XA COMMIT 'xa1'; +connection slave; +include/stop_slave.inc +connection master1; +XA START 'xa2'; +INSERT INTO t VALUES (40); +XA END 'xa2'; +XA PREPARE 'xa2'; +SET GLOBAL DEBUG_DBUG="d,simulate_crash_after_binlog_commit_or_rollback"; +XA COMMIT 'xa2'; +ERROR HY000: Lost connection to MySQL server during query +connection master1; +connection master; +connection default; +connection server_1; +connection master; +connection slave; +include/start_slave.inc +connection master; +SELECT * FROM t; +f +20 +40 +XA RECOVER; +formatID gtrid_length bqual_length data +XA COMMIT 'xa2'; +ERROR XAE04: XAER_NOTA: Unknown XID +SELECT * FROM t; +f +20 +40 +connection slave; +SELECT * FROM t; +f +20 +40 +connection master; +DROP TABLE t; +connection slave; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_xa_event_apply_failure_sync.result b/mysql-test/suite/rpl/r/rpl_xa_event_apply_failure_sync.result new file mode 100644 index 00000000000..dc9930b77b1 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_xa_event_apply_failure_sync.result @@ -0,0 +1,60 @@ +include/master-slave.inc +[connection master] +connect master2,localhost,root,,; +connection master; +CALL mtr.add_suppression("Found 1 prepared XA transactions"); +CALL mtr.add_suppression("Failed to execute binlog query event"); +CALL mtr.add_suppression("Recovery: Error .Out of memory.."); +CALL mtr.add_suppression("Crash recovery failed."); +CALL mtr.add_suppression("Can.t init tc log"); +CALL mtr.add_suppression("Aborting"); +CREATE TABLE t ( f INT ) ENGINE=INNODB; +XA START 'xa1'; +INSERT INTO t VALUES (20); +XA END 'xa1'; +XA PREPARE 'xa1'; +XA COMMIT 'xa1'; +connection slave; +include/stop_slave.inc +connection master1; +XA START 'xa2'; +INSERT INTO t VALUES (40); +XA END 'xa2'; +XA PREPARE 'xa2'; +SET GLOBAL DEBUG_DBUG="d,simulate_crash_after_binlog_commit_or_rollback"; +XA COMMIT 'xa2'; +ERROR HY000: Lost connection to MySQL server during query +connection master1; +connection master; +connection default; +connection default; +connection master; +*** must be no 'xa2' commit seen, as it's still prepared: +SELECT * FROM t; +f +20 +XA RECOVER; +formatID gtrid_length bqual_length data +1 3 0 xa2 +SET GLOBAL DEBUG_DBUG=""; +SET SQL_LOG_BIN=0; +XA COMMIT 'xa2'; +SET SQL_LOG_BIN=1; +connection server_1; +connection master; +connection slave; +include/start_slave.inc +connection master; +SELECT * FROM t; +f +20 +40 +connection slave; +SELECT * FROM t; +f +20 +40 +connection master; +DROP TABLE t; +connection slave; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_xa_prepare_commit_prepare_sync.result b/mysql-test/suite/rpl/r/rpl_xa_prepare_commit_prepare_sync.result new file mode 100644 index 00000000000..9ba24716639 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_xa_prepare_commit_prepare_sync.result @@ -0,0 +1,48 @@ +include/master-slave.inc +[connection master] +connect master2,localhost,root,,; +connection master; +CALL mtr.add_suppression("Found 1 prepared XA transactions"); +CREATE TABLE t ( f INT ) ENGINE=INNODB; +XA START 'xa1'; +INSERT INTO t VALUES (20); +XA END 'xa1'; +XA PREPARE 'xa1'; +XA COMMIT 'xa1'; +connection slave; +include/stop_slave.inc +connection master1; +XA START 'xa2'; +INSERT INTO t VALUES (40); +XA END 'xa2'; +SET GLOBAL DEBUG_DBUG="d,simulate_crash_after_binlog_prepare"; +XA PREPARE 'xa2'; +ERROR HY000: Lost connection to MySQL server during query +connection master1; +connection master; +connection default; +connection server_1; +connection master; +connection slave; +include/start_slave.inc +connection master; +SELECT * FROM t; +f +20 +XA RECOVER; +formatID gtrid_length bqual_length data +1 3 0 xa2 +XA COMMIT 'xa2'; +SELECT * FROM t; +f +20 +40 +connection slave; +SELECT * FROM t; +f +20 +40 +connection master; +DROP TABLE t; +connection slave; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_xa_prepare_crash_safe_sync.result b/mysql-test/suite/rpl/r/rpl_xa_prepare_crash_safe_sync.result new file mode 100644 index 00000000000..99baf59a3c1 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_xa_prepare_crash_safe_sync.result @@ -0,0 +1,62 @@ +include/master-slave.inc +[connection master] +connect master2,localhost,root,,; +connection master; +CALL mtr.add_suppression("Found 1 prepared XA transactions"); +CALL mtr.add_suppression("Found 2 prepared XA transactions"); +CALL mtr.add_suppression("Found 3 prepared XA transactions"); +CREATE TABLE t ( f INT ) ENGINE=INNODB; +XA START 'xa1'; +INSERT INTO t VALUES (20); +XA END 'xa1'; +XA PREPARE 'xa1'; +connection slave; +include/stop_slave.inc +connection master1; +use test; +xa start 'xa2'; +insert into t values (30); +xa end 'xa2'; +SET DEBUG_SYNC="simulate_hang_after_binlog_prepare SIGNAL reached WAIT_FOR go"; +xa prepare 'xa2'; +connection master2; +XA START 'xa3'; +INSERT INTO t VALUES (40); +XA END 'xa3'; +SET GLOBAL DEBUG_DBUG="d,simulate_crash_after_binlog_prepare"; +XA PREPARE 'xa3'; +ERROR HY000: Lost connection to MySQL server during query +connection master1; +ERROR HY000: Lost connection to MySQL server during query +connection master; +connection default; +connection server_1; +connection master; +connection slave; +include/start_slave.inc +connection master; +SELECT * FROM t; +f +XA RECOVER; +formatID gtrid_length bqual_length data +1 3 0 xa3 +1 3 0 xa1 +1 3 0 xa2 +XA COMMIT 'xa1'; +XA COMMIT 'xa2'; +XA COMMIT 'xa3'; +SELECT * FROM t; +f +20 +30 +40 +connection slave; +SELECT * FROM t; +f +20 +30 +40 +connection master; +DROP TABLE t; +connection slave; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_xa_rollback_commit_crash_safe_sync.result b/mysql-test/suite/rpl/r/rpl_xa_rollback_commit_crash_safe_sync.result new file mode 100644 index 00000000000..dc26c224ea9 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_xa_rollback_commit_crash_safe_sync.result @@ -0,0 +1,47 @@ +include/master-slave.inc +[connection master] +connect master2,localhost,root,,; +connection master; +CALL mtr.add_suppression("Found 1 prepared XA transactions"); +CREATE TABLE t ( f INT ) ENGINE=INNODB; +XA START 'xa1'; +INSERT INTO t VALUES (20); +XA END 'xa1'; +XA PREPARE 'xa1'; +XA COMMIT 'xa1'; +connection slave; +include/stop_slave.inc +connection master1; +XA START 'xa2'; +INSERT INTO t VALUES (40); +XA END 'xa2'; +XA PREPARE 'xa2'; +SET GLOBAL DEBUG_DBUG="d,simulate_crash_after_binlog_commit_or_rollback"; +XA ROLLBACK 'xa2'; +ERROR HY000: Lost connection to MySQL server during query +connection master1; +connection master; +connection default; +connection server_1; +connection master; +connection slave; +include/start_slave.inc +connection master; +SELECT * FROM t; +f +20 +XA RECOVER; +formatID gtrid_length bqual_length data +XA ROLLBACK 'xa2'; +ERROR XAE04: XAER_NOTA: Unknown XID +SELECT * FROM t; +f +20 +connection slave; +SELECT * FROM t; +f +20 +connection master; +DROP TABLE t; +connection slave; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_binlog_commit_crash_safe.opt b/mysql-test/suite/rpl/t/rpl_binlog_commit_crash_safe.opt new file mode 100644 index 00000000000..8547d377417 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_binlog_commit_crash_safe.opt @@ -0,0 +1 @@ +--sync_binlog=1 --innodb_flush_log_at_trx_commit=1 diff --git a/mysql-test/suite/rpl/t/rpl_binlog_commit_crash_safe.test b/mysql-test/suite/rpl/t/rpl_binlog_commit_crash_safe.test new file mode 100644 index 00000000000..714ae16859d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_binlog_commit_crash_safe.test @@ -0,0 +1,42 @@ +# ==== Purpose ==== +# +# Test verifies that Binlog Commits statements are crash safe. +# +# ==== Implementation ==== +# Create a innodb insert/update/delete and crash the server after binlog +# commit. Roll forward recovery should work. +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +--connection master + +CREATE TABLE t ( f INT) ENGINE=INNODB; +INSERT INTO t values(1); +--sync_slave_with_master + + +##Insert Block +--let $exec_query= INSERT INTO t values(10) +--source include/binlog_commit_crash_crud.inc + + +##Update Block +--let $exec_query= update t set f= 2 where f= 1 +--source include/binlog_commit_crash_crud.inc + + +##Delete Block +--let $exec_query= delete from t where f= 2 +--source include/binlog_commit_crash_crud.inc + +--connection master +SELECT * FROM t; +--sync_slave_with_master +SELECT * FROM t; + +--connection master +DROP TABLE t; +--sync_slave_with_master +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_xa_commit_crash_safe_innodb_sync.opt b/mysql-test/suite/rpl/t/rpl_xa_commit_crash_safe_innodb_sync.opt new file mode 100644 index 00000000000..8547d377417 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_xa_commit_crash_safe_innodb_sync.opt @@ -0,0 +1 @@ +--sync_binlog=1 --innodb_flush_log_at_trx_commit=1 diff --git a/mysql-test/suite/rpl/t/rpl_xa_commit_crash_safe_innodb_sync.test b/mysql-test/suite/rpl/t/rpl_xa_commit_crash_safe_innodb_sync.test new file mode 100644 index 00000000000..e972e3f09de --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_xa_commit_crash_safe_innodb_sync.test @@ -0,0 +1,98 @@ +# ==== Purpose ==== +# +# Test verifies that XA COMMIT statements are crash safe. +# +# ==== Implementation ==== +# +# Steps: +# 0 - Generate 2 explicit XA transactions. 'xa1' and 'xa2'. +# 'xa1' will be prepared and committed. +# 1 - For 'xa2' let the XA COMMIT be done in binary log and crash the +# server so that it is not committed in engine. +# 2 - Restart the server. The recovery code should successfully recover +# 'xa2'. The COMMIT should be executed during recovery. +# 3 - Check the data in table. Both rows should be present in table. +# 4 - Trying to commit 'xa2' should report unknown 'XA' error as COMMIT is +# already complete during recovery. +# +# ==== References ==== +# +# MDEV-21469: Implement crash-safe logging of the user XA + + +--source include/have_innodb.inc +--source include/master-slave.inc +--source include/have_debug.inc + +connect (master2,localhost,root,,); +--connection master +CALL mtr.add_suppression("Found 1 prepared XA transactions"); + +CREATE TABLE t ( f INT ) ENGINE=INNODB; +XA START 'xa1'; +INSERT INTO t VALUES (20); +XA END 'xa1'; +XA PREPARE 'xa1'; +XA COMMIT 'xa1'; +--sync_slave_with_master +--source include/stop_slave.inc + +--connection master1 +XA START 'xa2'; +INSERT INTO t VALUES (40); +XA END 'xa2'; +XA PREPARE 'xa2'; + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait +EOF + +SET GLOBAL DEBUG_DBUG="d,simulate_crash_after_binlog_commit_or_rollback"; +--error 2013 # CR_SERVER_LOST +XA COMMIT 'xa2'; +--source include/wait_until_disconnected.inc + +--connection master1 +--source include/wait_until_disconnected.inc + +--connection master +--source include/wait_until_disconnected.inc + +# +# Server restart +# +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart +EOF + +connection default; +--enable_reconnect +--source include/wait_until_connected_again.inc + +# rpl_end.inc needs to use the connection server_1 +connection server_1; +--enable_reconnect +--source include/wait_until_connected_again.inc + +--connection master +--enable_reconnect +--source include/wait_until_connected_again.inc + +--connection slave +--source include/start_slave.inc +--sync_with_master + +--connection master +SELECT * FROM t; +XA RECOVER; +--error 1397 # ER_XAER_NOTA +XA COMMIT 'xa2'; +SELECT * FROM t; +--sync_slave_with_master + +SELECT * FROM t; + +--connection master +DROP TABLE t; +--sync_slave_with_master +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_xa_event_apply_failure_sync.opt b/mysql-test/suite/rpl/t/rpl_xa_event_apply_failure_sync.opt new file mode 100644 index 00000000000..8547d377417 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_xa_event_apply_failure_sync.opt @@ -0,0 +1 @@ +--sync_binlog=1 --innodb_flush_log_at_trx_commit=1 diff --git a/mysql-test/suite/rpl/t/rpl_xa_event_apply_failure_sync.test b/mysql-test/suite/rpl/t/rpl_xa_event_apply_failure_sync.test new file mode 100644 index 00000000000..14cebbd9b13 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_xa_event_apply_failure_sync.test @@ -0,0 +1,119 @@ +# ==== Purpose ==== +# +# Test verifies that if for some reason an event cannot be applied during +# recovery, appropriate error is reported. +# +# ==== Implementation ==== +# +# Steps: +# 0 - Generate 2 explicit XA transactions. 'xa1' and 'xa2'. +# 'xa1' will be prepared and committed. +# 1 - For 'xa2' let the XA COMMIT be done in binary log and crash the +# server so that it is not committed in engine. +# 2 - Restart the server. Using debug simulation point make XA COMMIT 'xa2' +# execution to fail. The server will resume anyway +# to leave the error in the errlog (see "Recovery: Error.."). +# 3 - Work around the simulated failure with Commit once again +# from a connection that turns OFF binlogging. +# Slave must catch up with the master. +# +# ==== References ==== +# +# MDEV-21469: Implement crash-safe logging of the user XA + + +--source include/have_innodb.inc +--source include/master-slave.inc +--source include/have_debug.inc + +connect (master2,localhost,root,,); +--connection master +CALL mtr.add_suppression("Found 1 prepared XA transactions"); +CALL mtr.add_suppression("Failed to execute binlog query event"); +CALL mtr.add_suppression("Recovery: Error .Out of memory.."); +CALL mtr.add_suppression("Crash recovery failed."); +CALL mtr.add_suppression("Can.t init tc log"); +CALL mtr.add_suppression("Aborting"); + +CREATE TABLE t ( f INT ) ENGINE=INNODB; +XA START 'xa1'; +INSERT INTO t VALUES (20); +XA END 'xa1'; +XA PREPARE 'xa1'; +XA COMMIT 'xa1'; +--sync_slave_with_master +--source include/stop_slave.inc + +--connection master1 +XA START 'xa2'; +INSERT INTO t VALUES (40); +XA END 'xa2'; +XA PREPARE 'xa2'; + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait +EOF + +SET GLOBAL DEBUG_DBUG="d,simulate_crash_after_binlog_commit_or_rollback"; +--error 2013 # CR_SERVER_LOST +XA COMMIT 'xa2'; +--source include/wait_until_disconnected.inc + +--connection master1 +--source include/wait_until_disconnected.inc + +--connection master +--source include/wait_until_disconnected.inc + +# +# Server restart +# +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart: --debug-dbug=d,trans_xa_commit_fail +EOF + +connection default; +--source include/wait_until_disconnected.inc + +connection default; +--enable_reconnect +--source include/wait_until_connected_again.inc + +--connection master +--enable_reconnect +--echo *** must be no 'xa2' commit seen, as it's still prepared: +SELECT * FROM t; +XA RECOVER; + +# Commit it manually now to work around the extra binlog record +# by turning binlogging OFF by the connection. + +SET GLOBAL DEBUG_DBUG=""; +SET SQL_LOG_BIN=0; +--error 0 +XA COMMIT 'xa2'; +SET SQL_LOG_BIN=1; + + +# rpl_end.inc needs to use the connection server_1 +connection server_1; +--enable_reconnect +--source include/wait_until_connected_again.inc + +--connection master +--source include/wait_until_connected_again.inc + +--connection slave +--source include/start_slave.inc +--sync_with_master + +--connection master +SELECT * FROM t; + +--sync_slave_with_master +SELECT * FROM t; + +--connection master +DROP TABLE t; +--sync_slave_with_master +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_xa_prepare_commit_prepare_sync.opt b/mysql-test/suite/rpl/t/rpl_xa_prepare_commit_prepare_sync.opt new file mode 100644 index 00000000000..8547d377417 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_xa_prepare_commit_prepare_sync.opt @@ -0,0 +1 @@ +--sync_binlog=1 --innodb_flush_log_at_trx_commit=1 diff --git a/mysql-test/suite/rpl/t/rpl_xa_prepare_commit_prepare_sync.test b/mysql-test/suite/rpl/t/rpl_xa_prepare_commit_prepare_sync.test new file mode 100644 index 00000000000..7b987c7f29b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_xa_prepare_commit_prepare_sync.test @@ -0,0 +1,95 @@ +# ==== Purpose ==== +# +# Test verifies that XA PREPARE transactions are crash safe. +# +# ==== Implementation ==== +# +# Steps: +# 0 - Generate 2 explicit XA transactions. 'xa1' and 'xa2'. +# 'xa1' will be prepared and committed. +# 1 - For 'xa2' let the XA PREPARE be done in binary log and crash the +# server so that it is not prepared in engine. +# 2 - Restart the server. The recovery code should successfully recover +# 'xa2'. +# 3 - When server is up, execute XA RECOVER and verify that 'xa2' is +# present. +# 4 - Commit the XA transaction and verify its correctness. +# +# ==== References ==== +# +# MDEV-21469: Implement crash-safe logging of the user XA + +--source include/have_innodb.inc +--source include/master-slave.inc +--source include/have_debug.inc + +connect (master2,localhost,root,,); +--connection master +CALL mtr.add_suppression("Found 1 prepared XA transactions"); + +CREATE TABLE t ( f INT ) ENGINE=INNODB; +XA START 'xa1'; +INSERT INTO t VALUES (20); +XA END 'xa1'; +XA PREPARE 'xa1'; +XA COMMIT 'xa1'; +--sync_slave_with_master +--source include/stop_slave.inc + +--connection master1 +XA START 'xa2'; +INSERT INTO t VALUES (40); +XA END 'xa2'; + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait +EOF + +SET GLOBAL DEBUG_DBUG="d,simulate_crash_after_binlog_prepare"; +--error 2013 # CR_SERVER_LOST +XA PREPARE 'xa2'; +--source include/wait_until_disconnected.inc + +--connection master1 +--source include/wait_until_disconnected.inc + +--connection master +--source include/wait_until_disconnected.inc + +# +# Server restart +# +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart +EOF + +connection default; +--enable_reconnect +--source include/wait_until_connected_again.inc + +# rpl_end.inc needs to use the connection server_1 +connection server_1; +--enable_reconnect +--source include/wait_until_connected_again.inc + +--connection master +--enable_reconnect +--source include/wait_until_connected_again.inc + +--connection slave +--source include/start_slave.inc +--sync_with_master + +--connection master +SELECT * FROM t; +XA RECOVER; +XA COMMIT 'xa2'; +SELECT * FROM t; +--sync_slave_with_master + +SELECT * FROM t; + +--connection master +DROP TABLE t; +--sync_slave_with_master +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_xa_prepare_crash_safe_sync.opt b/mysql-test/suite/rpl/t/rpl_xa_prepare_crash_safe_sync.opt new file mode 100644 index 00000000000..8547d377417 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_xa_prepare_crash_safe_sync.opt @@ -0,0 +1 @@ +--sync_binlog=1 --innodb_flush_log_at_trx_commit=1 diff --git a/mysql-test/suite/rpl/t/rpl_xa_prepare_crash_safe_sync.test b/mysql-test/suite/rpl/t/rpl_xa_prepare_crash_safe_sync.test new file mode 100644 index 00000000000..9d2c5cce528 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_xa_prepare_crash_safe_sync.test @@ -0,0 +1,117 @@ +# ==== Purpose ==== +# +# Test verifies that XA PREPARE transactions are crash safe. +# +# ==== Implementation ==== +# +# Steps: +# 0 - Generate 3 explicit XA transactions. 'xa1', 'xa2' and 'xa3'. +# Using debug simulation hold the execution of second XA PREPARE +# statement after the XA PREPARE is written to the binary log. +# With this the prepare will not be done in engine. +# 1 - For 'xa3' allow the PREPARE statement to be written to binary log and +# simulate server crash. +# 2 - Restart the server. The recovery code should successfully recover +# 'xa2' and 'xa3'. +# 3 - When server is up, execute XA RECOVER and verify that 'xa2' and 'xa3' +# are present along with 'xa1'. +# 4 - Commit all the XA transactions and verify their correctness. +# +# ==== References ==== +# +# MDEV-21469: Implement crash-safe logging of the user XA + + +--source include/have_innodb.inc +--source include/master-slave.inc +--source include/have_debug.inc + +connect (master2,localhost,root,,); +--connection master +CALL mtr.add_suppression("Found 1 prepared XA transactions"); +CALL mtr.add_suppression("Found 2 prepared XA transactions"); +CALL mtr.add_suppression("Found 3 prepared XA transactions"); + +CREATE TABLE t ( f INT ) ENGINE=INNODB; +XA START 'xa1'; +INSERT INTO t VALUES (20); +XA END 'xa1'; +XA PREPARE 'xa1'; +--sync_slave_with_master +--source include/stop_slave.inc + +--connection master1 +use test; +xa start 'xa2'; +insert into t values (30); +xa end 'xa2'; +SET DEBUG_SYNC="simulate_hang_after_binlog_prepare SIGNAL reached WAIT_FOR go"; +send xa prepare 'xa2'; + +--connection master2 +let $wait_condition= + SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE STATE like "debug sync point: simulate_hang_after_binlog_prepare%"; +--source include/wait_condition.inc + +XA START 'xa3'; +INSERT INTO t VALUES (40); +XA END 'xa3'; + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait +EOF + +SET GLOBAL DEBUG_DBUG="d,simulate_crash_after_binlog_prepare"; +--error 2013 # CR_SERVER_LOST +XA PREPARE 'xa3'; +--source include/wait_until_disconnected.inc + +--connection master1 +--error 2013 +--reap +--source include/wait_until_disconnected.inc + +--connection master +--source include/wait_until_disconnected.inc + +# +# Server restart +# +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart +EOF + +connection default; +--enable_reconnect +--source include/wait_until_connected_again.inc + +# rpl_end.inc needs to use the connection server_1 +connection server_1; +--enable_reconnect +--source include/wait_until_connected_again.inc + +--connection master +--enable_reconnect +--source include/wait_until_connected_again.inc + + +--connection slave +--source include/start_slave.inc +--sync_with_master + +--connection master +SELECT * FROM t; +XA RECOVER; +XA COMMIT 'xa1'; +XA COMMIT 'xa2'; +XA COMMIT 'xa3'; +SELECT * FROM t; +--sync_slave_with_master + +SELECT * FROM t; + +--connection master +DROP TABLE t; +--sync_slave_with_master +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_xa_rollback_commit_crash_safe_sync.opt b/mysql-test/suite/rpl/t/rpl_xa_rollback_commit_crash_safe_sync.opt new file mode 100644 index 00000000000..8547d377417 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_xa_rollback_commit_crash_safe_sync.opt @@ -0,0 +1 @@ +--sync_binlog=1 --innodb_flush_log_at_trx_commit=1 diff --git a/mysql-test/suite/rpl/t/rpl_xa_rollback_commit_crash_safe_sync.test b/mysql-test/suite/rpl/t/rpl_xa_rollback_commit_crash_safe_sync.test new file mode 100644 index 00000000000..1d19f96116e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_xa_rollback_commit_crash_safe_sync.test @@ -0,0 +1,97 @@ +# ==== Purpose ==== +# +# Test verifies that XA COMMIT statements are crash safe. +# +# ==== Implementation ==== +# +# Steps: +# 0 - Generate 2 explicit XA transactions. 'xa1' and 'xa2'. +# 'xa1' will be prepared and committed. +# 1 - For 'xa2' let the XA ROLLBACK be done in binary log and crash the +# server so that it is not committed in engine. +# 2 - Restart the server. The recovery code should successfully recover +# 'xa2'. The ROLLBACK should be executed during recovery. +# 3 - Check the data in table. Only one row should be present in table. +# 4 - Trying to rollback 'xa2' should report unknown 'XA' error as rollback +# is already complete during recovery. +# +# ==== References ==== +# +# MDEV-21469: Implement crash-safe logging of the user XA + +--source include/have_innodb.inc +--source include/master-slave.inc +--source include/have_debug.inc + +connect (master2,localhost,root,,); +--connection master +CALL mtr.add_suppression("Found 1 prepared XA transactions"); + +CREATE TABLE t ( f INT ) ENGINE=INNODB; +XA START 'xa1'; +INSERT INTO t VALUES (20); +XA END 'xa1'; +XA PREPARE 'xa1'; +XA COMMIT 'xa1'; +--sync_slave_with_master +--source include/stop_slave.inc + +--connection master1 +XA START 'xa2'; +INSERT INTO t VALUES (40); +XA END 'xa2'; +XA PREPARE 'xa2'; + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait +EOF + +SET GLOBAL DEBUG_DBUG="d,simulate_crash_after_binlog_commit_or_rollback"; +--error 2013 # CR_SERVER_LOST +XA ROLLBACK 'xa2'; +--source include/wait_until_disconnected.inc + +--connection master1 +--source include/wait_until_disconnected.inc + +--connection master +--source include/wait_until_disconnected.inc + +# +# Server restart +# +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart +EOF + +connection default; +--enable_reconnect +--source include/wait_until_connected_again.inc + +# rpl_end.inc needs to use the connection server_1 +connection server_1; +--enable_reconnect +--source include/wait_until_connected_again.inc + +--connection master +--enable_reconnect +--source include/wait_until_connected_again.inc + +--connection slave +--source include/start_slave.inc +--sync_with_master + +--connection master +SELECT * FROM t; +XA RECOVER; +--error 1397 # ER_XAER_NOTA +XA ROLLBACK 'xa2'; +SELECT * FROM t; +--sync_slave_with_master + +SELECT * FROM t; + +--connection master +DROP TABLE t; +--sync_slave_with_master +--source include/rpl_end.inc diff --git a/sql/log.cc b/sql/log.cc index ec038e42586..fc025b43fa6 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2203,6 +2203,9 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all) */ cache_mngr->reset(false, true); THD_STAGE_INFO(thd, org_stage); + //todo + DBUG_EXECUTE_IF("simulate_crash_after_binlog_commit_or_rollback", + DBUG_SUICIDE();); DBUG_RETURN(error); } diff --git a/storage/rocksdb/mysql-test/rocksdb_rpl/t/rpl_rocksdb_binlog_recover.inc b/storage/rocksdb/mysql-test/rocksdb_rpl/t/rpl_rocksdb_binlog_recover.inc new file mode 100644 index 00000000000..f27f1b64213 --- /dev/null +++ b/storage/rocksdb/mysql-test/rocksdb_rpl/t/rpl_rocksdb_binlog_recover.inc @@ -0,0 +1,40 @@ +# +# Execute given queries and crash(and restart) the server after binary log +# commit +# @@input $exec_query_1 +# @@input $exec_query_2 + +--connection master +set autocommit= 0; +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait +EOF + +start transaction; + --eval $exec_query_1 + --eval $exec_query_2 +SET GLOBAL DEBUG_DBUG="d,simulate_crash_after_binlog_commit_or_rollback"; +--error 2013 # CR_SERVER_LOST +commit; + +--source include/wait_until_disconnected.inc + +# Server restart +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart +EOF + +connection default; +--enable_reconnect +--source include/wait_until_connected_again.inc + +# rpl_end.inc needs to use the connection server_1 +connection server_1; +--enable_reconnect +--source include/wait_until_connected_again.inc + +--connection master +--enable_reconnect +--source include/wait_until_connected_again.inc +set autocommit= 1; +SET GLOBAL DEBUG_DBUG="reset"; diff --git a/storage/rocksdb/mysql-test/rocksdb_rpl/t/rpl_rocksdb_binlog_recover.opt b/storage/rocksdb/mysql-test/rocksdb_rpl/t/rpl_rocksdb_binlog_recover.opt new file mode 100644 index 00000000000..8547d377417 --- /dev/null +++ b/storage/rocksdb/mysql-test/rocksdb_rpl/t/rpl_rocksdb_binlog_recover.opt @@ -0,0 +1 @@ +--sync_binlog=1 --innodb_flush_log_at_trx_commit=1 diff --git a/storage/rocksdb/mysql-test/rocksdb_rpl/t/rpl_rocksdb_binlog_recover.test b/storage/rocksdb/mysql-test/rocksdb_rpl/t/rpl_rocksdb_binlog_recover.test new file mode 100644 index 00000000000..caa3a7ddf90 --- /dev/null +++ b/storage/rocksdb/mysql-test/rocksdb_rpl/t/rpl_rocksdb_binlog_recover.test @@ -0,0 +1,49 @@ +# ==== Purpose ==== +# +# Test verifies that MultiEngine COMMITS statements are crash safe(crash after +# Binlog sync). +# +# ==== Implementation ==== +# Create a innodb and insert/update/delete and crash the server after binlog +# commit. Roll forward recovery should work. +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +--connection master + +CREATE TABLE t1 ( f INT) ENGINE=INNODB; +CREATE TABLE t2 ( f INT) ENGINE=INNODB; +INSERT INTO t1 values(1); +INSERT INTO t2 values(1); +--sync_slave_with_master + + +##Insert Block +--let $exec_query_1= INSERT INTO t1 values(10) +--let $exec_query_2= INSERT INTO t2 values(10) +--source rpl_rocksdb_binlog_recover.inc + + +##Update Block +--let $exec_query_1= update t1 set f= 2 where f= 1 +--let $exec_query_2= update t2 set f= 2 where f= 1 +--source rpl_rocksdb_binlog_recover.inc + + +##Delete Block +--let $exec_query_1= delete from t1 where f= 2 +--let $exec_query_2= delete from t2 where f= 2 +--source rpl_rocksdb_binlog_recover.inc + +--connection master +SELECT * FROM t; +--sync_slave_with_master +SELECT * FROM t; + +--connection master +DROP TABLE t; +--sync_slave_with_master +--source include/rpl_end.inc + |