mirror of
https://github.com/MariaDB/server.git
synced 2025-02-09 23:24:11 +01:00
![Brandon Nesterenko](/assets/img/avatar_default.png)
This commit makes replicas crash-safe by default by changing the Using_Gtid value to be Slave_Pos on a fresh slave start and after RESET SLAVE is issued. If the primary server does not support GTIDs (i.e., version < 10), the replica will fall back to Using_Gtid=No on slave start and after RESET SLAVE. The following additional informational messages/warnings are added: 1. When Using_Gtid is automatically changed. That is, if RESET SLAVE reverts Using_Gtid back to Slave_Pos, or Using_Gtid is inferred to No from a CHANGE MASTER TO given with log coordinates without MASTER_USE_GTID. 2. If options are ignored in CHANGE MASTER TO. If CHANGE MASTER TO is given with log coordinates, yet also specifies MASTER_USE_GTID=Slave_Pos, a warning message is given that the log coordinate options are ignored. Additionally, an MTR macro has been added for RESET SLAVE, reset_slave.inc, which provides modes/options for resetting a slave in log coordinate or gtid modes. When in log coordinates mode, the macro will execute CHANGE MASTER TO MASTER_USE_GTID=No after the RESET SLAVE command. When in GTID mode, an extra parameter, reset_slave_keep_gtid_state, can be set to reset or preserve the value of gtid_slave_pos. Reviewed By: =========== Andrei Elkin <andrei.elkin@mariadb.com>
137 lines
4 KiB
Text
137 lines
4 KiB
Text
# ==== Purpose ====
|
|
#
|
|
# This test will generate two XA transactions on the master in a way that
|
|
# they will block each other on the slave if the transaction isolation level
|
|
# used by the slave applier is more restrictive than the READ COMMITTED one.
|
|
#
|
|
# Consider:
|
|
# E=execute, P=prepare, C=commit;
|
|
# 1=first transaction, 2=second transaction;
|
|
#
|
|
# Master does: E1, E2, P2, P1, C1, C2
|
|
# Slave does: E2, P2, E1, P1, C1, C2
|
|
#
|
|
# The transactions are designed so that, if the applier transaction isolation
|
|
# level is more restrictive than the READ COMMITTED, E1 will be blocked on
|
|
# the slave waiting for gap locks to be released.
|
|
#
|
|
# Step 1
|
|
#
|
|
# The test will verify that the transactions don't block each other because
|
|
# the applier thread automatically changed the isolation level.
|
|
#
|
|
# Step 2
|
|
#
|
|
# The test will verify that applying master's binary log dump in slave doesn't
|
|
# block because mysqlbinlog is informing the isolation level to be used.
|
|
#
|
|
# ==== Related Bugs and Worklogs ====
|
|
#
|
|
# BUG#25040331: INTERLEAVED XA TRANSACTIONS MAY DEADLOCK SLAVE APPLIER WITH
|
|
# REPEATABLE READ
|
|
#
|
|
--source include/have_debug.inc
|
|
--source include/have_innodb.inc
|
|
# The test case only make sense for RBR
|
|
--source include/have_binlog_format_row.inc
|
|
--source include/master-slave.inc
|
|
|
|
--connection slave
|
|
# To hit the issue, we need to split the data in two pages.
|
|
# This global variable will help us.
|
|
SET @saved_innodb_limit_optimistic_insert_debug = @@GLOBAL.innodb_limit_optimistic_insert_debug;
|
|
SET @@GLOBAL.innodb_limit_optimistic_insert_debug = 2;
|
|
|
|
#
|
|
# Step 1 - Using async replication
|
|
#
|
|
|
|
# Let's generate the workload on the master
|
|
--connection master
|
|
CREATE TABLE t1 (
|
|
c1 INT NOT NULL,
|
|
KEY(c1)
|
|
) ENGINE=InnoDB;
|
|
|
|
CREATE TABLE t2 (
|
|
c1 INT NOT NULL,
|
|
FOREIGN KEY(c1) REFERENCES t1(c1)
|
|
) ENGINE=InnoDB;
|
|
|
|
INSERT INTO t1 VALUES (1), (3), (4);
|
|
|
|
--connection master1
|
|
XA START 'XA1';
|
|
INSERT INTO t1 values(2);
|
|
XA END 'XA1';
|
|
|
|
# This transaction will reference the gap where XA1
|
|
# was inserted, and will be prepared and committed
|
|
# before XA1, so the slave will prepare it (but will
|
|
# not commit it) before preparing XA1.
|
|
--connection master
|
|
XA START 'XA2';
|
|
INSERT INTO t2 values(3);
|
|
XA END 'XA2';
|
|
|
|
# The XA2 prepare should be binary logged first
|
|
XA PREPARE 'XA2';
|
|
|
|
# The XA1 prepare should be binary logged
|
|
# after XA2 prepare and before XA2 commit.
|
|
--connection master1
|
|
XA PREPARE 'XA1';
|
|
|
|
# The commit order doesn't matter much for the issue being tested.
|
|
XA COMMIT 'XA1';
|
|
--connection master
|
|
XA COMMIT 'XA2';
|
|
|
|
# Everything is fine if the slave can sync with the master.
|
|
--source include/sync_slave_sql_with_master.inc
|
|
|
|
#
|
|
# Step 2 - Using mysqlbinlog dump to restore the salve
|
|
#
|
|
--source include/stop_slave.inc
|
|
DROP TABLE t2, t1;
|
|
RESET SLAVE;
|
|
RESET MASTER;
|
|
|
|
--connection master
|
|
--let $master_data_dir= `SELECT @@datadir`
|
|
--let $master_log_file= query_get_value(SHOW MASTER STATUS, File, 1)
|
|
--let $mysql_server= $MYSQL --defaults-group-suffix=.2
|
|
--echo Restore binary log from the master into the slave
|
|
--exec $MYSQL_BINLOG --force-if-open $master_data_dir/$master_log_file | $mysql_server
|
|
|
|
--let $diff_tables= master:test.t1, slave:test.t1
|
|
--source include/diff_tables.inc
|
|
--let $diff_tables= master:test.t2, slave:test.t2
|
|
--source include/diff_tables.inc
|
|
|
|
#
|
|
# Cleanup
|
|
#
|
|
--let $master_file= query_get_value(SHOW MASTER STATUS, File, 1)
|
|
--let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1)
|
|
DROP TABLE t2, t1;
|
|
|
|
## When GTID_MODE=OFF, we need to skip already applied transactions
|
|
--connection slave
|
|
#--let $gtid_mode= `SELECT @@GTID_MODE`
|
|
#if ($gtid_mode == OFF)
|
|
#{
|
|
# --disable_query_log
|
|
# --disable_result_log
|
|
# --eval CHANGE MASTER TO MASTER_LOG_FILE='$master_file', MASTER_LOG_POS=$master_pos
|
|
# --enable_result_log
|
|
# --enable_query_log
|
|
#}
|
|
--replace_result $master_file LOG_FILE $master_pos LOG_POS
|
|
--eval CHANGE MASTER TO MASTER_LOG_FILE='$master_file', MASTER_LOG_POS=$master_pos, MASTER_USE_GTID=NO
|
|
|
|
SET @@GLOBAL.innodb_limit_optimistic_insert_debug = @saved_innodb_limit_optimistic_insert_debug;
|
|
--source include/start_slave.inc
|
|
|
|
--source include/rpl_end.inc
|