mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
Merge 10.11 into 11.4
This commit is contained in:
42
mysql-test/suite/rpl/r/parallel_backup_xa_debug.result
Normal file
42
mysql-test/suite/rpl/r/parallel_backup_xa_debug.result
Normal file
@@ -0,0 +1,42 @@
|
||||
include/master-slave.inc
|
||||
[connection master]
|
||||
connection master;
|
||||
CREATE TABLE t (a INT) ENGINE = innodb;
|
||||
connection slave;
|
||||
include/stop_slave.inc
|
||||
SET @old_parallel_threads= @@GLOBAL.slave_parallel_threads;
|
||||
SET @old_parallel_mode = @@GLOBAL.slave_parallel_mode;
|
||||
SET @@global.slave_parallel_threads= 2;
|
||||
SET @@global.slave_parallel_mode = 'optimistic';
|
||||
connection master;
|
||||
# MDEV-35110
|
||||
SET @@gtid_seq_no=100;
|
||||
insert into t set a=1;
|
||||
xa start 'x';
|
||||
insert into t set a=2;
|
||||
xa end 'x';
|
||||
xa prepare 'x';
|
||||
connection slave;
|
||||
SET @@global.debug_dbug="+d,hold_worker_on_schedule";
|
||||
start slave;
|
||||
connection slave1;
|
||||
backup stage start;
|
||||
backup stage block_commit;
|
||||
connection slave;
|
||||
SET debug_sync = 'now SIGNAL continue_worker';
|
||||
SET debug_sync = RESET;
|
||||
connection slave1;
|
||||
backup stage end;
|
||||
connection master;
|
||||
xa rollback 'x';
|
||||
connection slave;
|
||||
# Clean up.
|
||||
connection slave;
|
||||
include/stop_slave.inc
|
||||
SET @@global.debug_dbug="";
|
||||
SET @@global.slave_parallel_threads= @old_parallel_threads;
|
||||
SET @@global.slave_parallel_mode = @old_parallel_mode;
|
||||
include/start_slave.inc
|
||||
connection server_1;
|
||||
DROP TABLE t;
|
||||
include/rpl_end.inc
|
@@ -9,7 +9,6 @@ CHANGE MASTER TO MASTER_USE_GTID=slave_pos;
|
||||
include/start_slave.inc
|
||||
connection master;
|
||||
"Test Case 1: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(1), gtid('')"
|
||||
include/wait_for_pattern_in_file.inc
|
||||
FOUND 1 /using_gtid\(1\), gtid\(\'\'\).*/ in mysqld.1.err
|
||||
connection slave;
|
||||
include/stop_slave.inc
|
||||
@@ -17,7 +16,6 @@ CHANGE MASTER TO MASTER_USE_GTID=no;
|
||||
include/start_slave.inc
|
||||
connection master;
|
||||
"Test Case 2: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(0), gtid('')"
|
||||
include/wait_for_pattern_in_file.inc
|
||||
FOUND 1 /using_gtid\(0\), gtid\(\'\'\).*/ in mysqld.1.err
|
||||
CREATE TABLE t (f INT) ENGINE=INNODB;
|
||||
INSERT INTO t VALUES(10);
|
||||
@@ -28,7 +26,6 @@ CHANGE MASTER TO MASTER_USE_GTID=slave_pos;
|
||||
include/start_slave.inc
|
||||
connection master;
|
||||
"Test Case 3: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(1), gtid('0-1-2')"
|
||||
include/wait_for_pattern_in_file.inc
|
||||
FOUND 1 /using_gtid\(1\), gtid\(\'0-1-2\'\).*/ in mysqld.1.err
|
||||
SET @@SESSION.gtid_domain_id=10;
|
||||
INSERT INTO t VALUES(20);
|
||||
@@ -39,7 +36,6 @@ CHANGE MASTER TO MASTER_USE_GTID=slave_pos;
|
||||
include/start_slave.inc
|
||||
connection master;
|
||||
"Test Case 4: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(1), gtid('0-1-2,10-1-1')"
|
||||
include/wait_for_pattern_in_file.inc
|
||||
FOUND 1 /using_gtid\(1\), gtid\(\'0-1-2,10-1-1\'\).*/ in mysqld.1.err
|
||||
"===== Clean up ====="
|
||||
SET GLOBAL LOG_WARNINGS=@org_log_warnings;
|
||||
|
@@ -0,0 +1,88 @@
|
||||
include/master-slave.inc
|
||||
[connection master]
|
||||
connection slave;
|
||||
include/stop_slave.inc
|
||||
set @old_enabled= @@global.rpl_semi_sync_slave_enabled;
|
||||
set @old_dbug= @@global.debug_dbug;
|
||||
set global rpl_semi_sync_slave_enabled= 1;
|
||||
connection master;
|
||||
set @old_enabled= @@global.rpl_semi_sync_master_enabled;
|
||||
set @old_timeout= @@global.rpl_semi_sync_master_timeout;
|
||||
set @old_wait_point= @@global.rpl_semi_sync_master_wait_point;
|
||||
set global rpl_semi_sync_master_enabled= 1;
|
||||
set global rpl_semi_sync_master_timeout= 2000;
|
||||
set global rpl_semi_sync_master_wait_point= AFTER_SYNC;
|
||||
connection slave;
|
||||
include/start_slave.inc
|
||||
# Ensure slave connection is semi-simulate_delay_semisync_slave_reply
|
||||
connection master;
|
||||
connection slave;
|
||||
#
|
||||
# Initialize test data
|
||||
connection master;
|
||||
create table t1 (a int) engine=innodb;
|
||||
include/save_master_gtid.inc
|
||||
connection slave;
|
||||
include/sync_with_master_gtid.inc
|
||||
include/stop_slave.inc
|
||||
set @@global.debug_dbug="+d,simulate_delay_semisync_slave_reply";
|
||||
include/start_slave.inc
|
||||
# Ensure connection is semi-sync
|
||||
connection master;
|
||||
connection slave;
|
||||
connection master;
|
||||
set @old_bgc_count= @@global.binlog_commit_wait_count;
|
||||
set @old_bgc_usec= @@global.binlog_commit_wait_usec;
|
||||
set @@global.binlog_commit_wait_count=1;
|
||||
set @@global.binlog_commit_wait_usec=100000;
|
||||
connection server_1;
|
||||
set debug_sync= "commit_after_release_LOCK_log SIGNAL ddl_binlogged WAIT_FOR ddl_cont";
|
||||
# T1 (DDL)
|
||||
create table t2 (a int);
|
||||
connect server_1_sync, localhost, root,,;
|
||||
connection server_1_sync;
|
||||
set debug_sync= "now WAIT_FOR ddl_binlogged";
|
||||
include/save_master_gtid.inc
|
||||
connection server_2;
|
||||
set debug_sync= "now WAIT_FOR io_thd_at_slave_reply";
|
||||
connection master;
|
||||
set debug_sync= "commit_before_get_LOCK_after_binlog_sync SIGNAL mdl_binlogged WAIT_FOR mdl_cont";
|
||||
# T2 (DML)
|
||||
insert into t1 values (100);;
|
||||
connection server_1_sync;
|
||||
set debug_sync= "now WAIT_FOR mdl_binlogged";
|
||||
# Both transactions binlogged and released LOCK_log, and are just before
|
||||
# wait_after_sync()
|
||||
set debug_sync= "now SIGNAL ddl_cont";
|
||||
set debug_sync= "now SIGNAL mdl_cont";
|
||||
connection server_2;
|
||||
# slave_reply for DDL
|
||||
set debug_sync= "now SIGNAL io_thd_do_reply";
|
||||
# slave_reply for MDL
|
||||
set debug_sync= "now WAIT_FOR io_thd_at_slave_reply";
|
||||
set debug_sync= "now SIGNAL io_thd_do_reply";
|
||||
# Reaping MDL..
|
||||
connection master;
|
||||
# ..done
|
||||
# Reaping DDL..
|
||||
connection server_1;
|
||||
# ..done
|
||||
#
|
||||
# Cleanup
|
||||
connection slave;
|
||||
include/stop_slave.inc
|
||||
set @@global.rpl_semi_sync_slave_enabled= @old_enabled;
|
||||
set @@global.debug_dbug= @old_dbug;
|
||||
include/start_slave.inc
|
||||
connection master;
|
||||
set @@global.binlog_commit_wait_count= @old_bgc_count;
|
||||
set @@global.binlog_commit_wait_usec= @old_bgc_usec;
|
||||
set @@global.rpl_semi_sync_master_enabled= @old_enabled;
|
||||
set @@global.rpl_semi_sync_master_timeout= @old_timeout;
|
||||
set @@global.rpl_semi_sync_master_wait_point= @old_wait_point;
|
||||
drop table t1, t2;
|
||||
include/save_master_gtid.inc
|
||||
connection slave;
|
||||
include/sync_with_master_gtid.inc
|
||||
include/rpl_end.inc
|
||||
# End of rpl_semi_sync_after_sync_coord_consistency.test
|
@@ -3,7 +3,7 @@ connection server_1;
|
||||
set @old_enabled= @@global.rpl_semi_sync_master_enabled;
|
||||
set @old_timeout= @@global.rpl_semi_sync_master_timeout;
|
||||
set global rpl_semi_sync_master_enabled= 1;
|
||||
set global rpl_semi_sync_master_timeout= 500;
|
||||
set global rpl_semi_sync_master_timeout= 2000;
|
||||
connection server_2;
|
||||
include/stop_slave.inc
|
||||
set @old_enabled= @@global.rpl_semi_sync_slave_enabled;
|
||||
@@ -14,12 +14,24 @@ include/start_slave.inc
|
||||
connection server_3;
|
||||
include/stop_slave.inc
|
||||
set @old_enabled= @@global.rpl_semi_sync_slave_enabled;
|
||||
set @old_dbug= @@global.debug_dbug;
|
||||
set global rpl_semi_sync_slave_enabled= 1;
|
||||
set global debug_dbug="+d,simulate_delay_semisync_slave_reply";
|
||||
include/start_slave.inc
|
||||
# Ensure primary recognizes both replicas are semi-sync
|
||||
connection server_1;
|
||||
connection server_1;
|
||||
create table t1 (a int);
|
||||
connection default;
|
||||
create table t1 (a int);;
|
||||
# Ensure both slaves get the event with the need_ack flag set (i.e. one
|
||||
# slave shouldn't be able to receive the event and send an ACK before
|
||||
# the dump thread for the other server prepares the event to send).
|
||||
connection server_3;
|
||||
set debug_sync= "now wait_for io_thd_at_slave_reply";
|
||||
connection server_2;
|
||||
set debug_sync= "now wait_for io_thd_at_slave_reply";
|
||||
connection server_3;
|
||||
set debug_sync= "now signal io_thd_do_reply";
|
||||
connection default;
|
||||
connection server_2;
|
||||
# Verifying server_2 did not send ACK
|
||||
connection server_3;
|
||||
@@ -27,15 +39,18 @@ connection server_3;
|
||||
connection server_1;
|
||||
# Verifying master's semi-sync status is still ON (This failed pre-MDEV-32960 fixes)
|
||||
# Verifying rpl_semi_sync_master_yes_tx incremented
|
||||
connection server_2;
|
||||
set debug_sync= "now signal io_thd_do_reply";
|
||||
#
|
||||
# Cleanup
|
||||
connection server_2;
|
||||
include/stop_slave.inc
|
||||
set global rpl_semi_sync_slave_enabled= @old_enabled;
|
||||
set global debug_dbug= @old_dbug;
|
||||
include/stop_slave.inc
|
||||
connection server_3;
|
||||
set global rpl_semi_sync_slave_enabled= @old_enabled;
|
||||
include/stop_slave.inc
|
||||
set global rpl_semi_sync_slave_enabled= @old_enabled;
|
||||
set global debug_dbug= @old_dbug;
|
||||
connection server_1;
|
||||
set global rpl_semi_sync_master_enabled= @old_enabled;
|
||||
set global rpl_semi_sync_master_timeout= @old_timeout;
|
||||
|
@@ -83,12 +83,26 @@ connection server_1;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
connection server_1_con2;
|
||||
#-- Wait until master recognizes a connection is awaiting semi-sync ACK
|
||||
connection server_2;
|
||||
set debug_sync= "now wait_for io_thd_at_slave_reply";
|
||||
connection server_3;
|
||||
set debug_sync= "now wait_for io_thd_at_slave_reply";
|
||||
connection server_1_con2;
|
||||
#-- Begin master shutdown
|
||||
SHUTDOWN WAIT FOR ALL SLAVES;
|
||||
connection server_2;
|
||||
# Waitng for shutdown to be delayed..
|
||||
FOUND 1 /Delaying shutdown to await semi-sync ACK/ in mysqld.1.err
|
||||
connection server_2;
|
||||
set debug_sync= "now signal io_thd_do_reply";
|
||||
connection server_3;
|
||||
set debug_sync= "now signal io_thd_do_reply";
|
||||
# Reaping transaction..
|
||||
connection server_1;
|
||||
ERROR HY000: Lost connection to server during query
|
||||
# Check logs to ensure shutdown was delayed
|
||||
FOUND 1 /Delaying shutdown to await semi-sync ACK/ in mysqld.1.err
|
||||
connection server_2;
|
||||
# Reaping shutdown..
|
||||
connection server_1_con2;
|
||||
# Validate slave data is in correct state
|
||||
connection server_2;
|
||||
select count(*)=1 from t1;
|
||||
@@ -184,12 +198,18 @@ connection server_1;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
connection server_1_con2;
|
||||
#-- Wait until master recognizes a connection is awaiting semi-sync ACK
|
||||
connection server_1_con2;
|
||||
#-- Begin master shutdown
|
||||
SHUTDOWN WAIT FOR ALL SLAVES;
|
||||
connection server_2;
|
||||
# Waitng for shutdown to be delayed..
|
||||
FOUND 2 /Delaying shutdown to await semi-sync ACK/ in mysqld.1.err
|
||||
# Reaping transaction..
|
||||
connection server_1;
|
||||
ERROR HY000: Lost connection to server during query
|
||||
# Check logs to ensure shutdown was delayed
|
||||
FOUND 2 /Delaying shutdown to await semi-sync ACK/ in mysqld.1.err
|
||||
connection server_2;
|
||||
# Reaping shutdown..
|
||||
connection server_1_con2;
|
||||
# Validate slave data is in correct state
|
||||
connection server_2;
|
||||
select count(*)=0 from t1;
|
||||
@@ -298,12 +318,22 @@ connection server_1;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
connection server_1_con2;
|
||||
#-- Wait until master recognizes a connection is awaiting semi-sync ACK
|
||||
connection server_3;
|
||||
set debug_sync= "now wait_for io_thd_at_slave_reply";
|
||||
connection server_1_con2;
|
||||
#-- Begin master shutdown
|
||||
SHUTDOWN WAIT FOR ALL SLAVES;
|
||||
connection server_2;
|
||||
# Waitng for shutdown to be delayed..
|
||||
FOUND 3 /Delaying shutdown to await semi-sync ACK/ in mysqld.1.err
|
||||
connection server_3;
|
||||
set debug_sync= "now signal io_thd_do_reply";
|
||||
# Reaping transaction..
|
||||
connection server_1;
|
||||
ERROR HY000: Lost connection to server during query
|
||||
# Check logs to ensure shutdown was delayed
|
||||
FOUND 3 /Delaying shutdown to await semi-sync ACK/ in mysqld.1.err
|
||||
connection server_2;
|
||||
# Reaping shutdown..
|
||||
connection server_1_con2;
|
||||
# Validate slave data is in correct state
|
||||
connection server_2;
|
||||
select count(*)=0 from t1;
|
||||
@@ -412,12 +442,22 @@ connection server_1;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
connection server_1_con2;
|
||||
#-- Wait until master recognizes a connection is awaiting semi-sync ACK
|
||||
connection server_3;
|
||||
set debug_sync= "now wait_for io_thd_at_slave_reply";
|
||||
connection server_1_con2;
|
||||
#-- Begin master shutdown
|
||||
SHUTDOWN WAIT FOR ALL SLAVES;
|
||||
connection server_2;
|
||||
# Waitng for shutdown to be delayed..
|
||||
FOUND 4 /Delaying shutdown to await semi-sync ACK/ in mysqld.1.err
|
||||
connection server_3;
|
||||
set debug_sync= "now signal io_thd_do_reply";
|
||||
# Reaping transaction..
|
||||
connection server_1;
|
||||
ERROR HY000: Lost connection to server during query
|
||||
# Check logs to ensure shutdown was delayed
|
||||
FOUND 4 /Delaying shutdown to await semi-sync ACK/ in mysqld.1.err
|
||||
connection server_2;
|
||||
# Reaping shutdown..
|
||||
connection server_1_con2;
|
||||
# Validate slave data is in correct state
|
||||
connection server_2;
|
||||
select count(*)=0 from t1;
|
||||
@@ -501,15 +541,20 @@ insert into t1 values (2);
|
||||
connection server_1;
|
||||
# Wait for thd to begin semi-sync wait..
|
||||
# ..done
|
||||
connection server_2;
|
||||
set debug_sync= "now wait_for io_thd_at_slave_reply";
|
||||
disconnect con1;
|
||||
connection default;
|
||||
connection con2;
|
||||
SHUTDOWN WAIT FOR ALL SLAVES;
|
||||
# Ensure the primary waited for the ACK of the killed thread
|
||||
# Waitng for shutdown to be delayed..
|
||||
connection server_2;
|
||||
FOUND 5 /Delaying shutdown to await semi-sync ACK/ in mysqld.1.err
|
||||
connection default;
|
||||
connection server_1;
|
||||
connection con2;
|
||||
connection server_2;
|
||||
set debug_sync= "now signal io_thd_do_reply";
|
||||
include/stop_slave.inc
|
||||
connection server_3;
|
||||
include/stop_slave.inc
|
||||
|
64
mysql-test/suite/rpl/t/parallel_backup_xa_debug.test
Normal file
64
mysql-test/suite/rpl/t/parallel_backup_xa_debug.test
Normal file
@@ -0,0 +1,64 @@
|
||||
# Verify deadlock between XA-PREPARE and BACKUP on the optimistic slave
|
||||
--source include/have_debug.inc
|
||||
--source include/have_debug_sync.inc
|
||||
--source include/have_innodb.inc
|
||||
# The test is not format specific, MIXED is required to optimize testing time
|
||||
--source include/have_binlog_format_mixed.inc
|
||||
--source include/master-slave.inc
|
||||
|
||||
--connection master
|
||||
CREATE TABLE t (a INT) ENGINE = innodb;
|
||||
|
||||
--sync_slave_with_master
|
||||
--source include/stop_slave.inc
|
||||
SET @old_parallel_threads= @@GLOBAL.slave_parallel_threads;
|
||||
SET @old_parallel_mode = @@GLOBAL.slave_parallel_mode;
|
||||
SET @@global.slave_parallel_threads= 2;
|
||||
SET @@global.slave_parallel_mode = 'optimistic';
|
||||
|
||||
--connection master
|
||||
--echo # MDEV-35110
|
||||
SET @@gtid_seq_no=100;
|
||||
insert into t set a=1;
|
||||
xa start 'x';
|
||||
insert into t set a=2;
|
||||
xa end 'x';
|
||||
xa prepare 'x';
|
||||
|
||||
--connection slave
|
||||
SET @@global.debug_dbug="+d,hold_worker_on_schedule";
|
||||
start slave;
|
||||
--let $wait_condition= SELECT count(*) = 1 FROM information_schema.processlist WHERE state LIKE "Waiting for prior transaction to commit"
|
||||
--source include/wait_condition.inc
|
||||
|
||||
--connection slave1
|
||||
backup stage start;
|
||||
--send backup stage block_commit
|
||||
|
||||
--connection slave
|
||||
--let $wait_condition= SELECT count(*) = 1 FROM information_schema.processlist WHERE state LIKE "Waiting for backup lock"
|
||||
SET debug_sync = 'now SIGNAL continue_worker';
|
||||
SET debug_sync = RESET;
|
||||
|
||||
--connection slave1
|
||||
reap;
|
||||
backup stage end;
|
||||
|
||||
--connection master
|
||||
xa rollback 'x';
|
||||
|
||||
--sync_slave_with_master
|
||||
|
||||
--echo # Clean up.
|
||||
--connection slave
|
||||
--source include/stop_slave.inc
|
||||
SET @@global.debug_dbug="";
|
||||
SET @@global.slave_parallel_threads= @old_parallel_threads;
|
||||
SET @@global.slave_parallel_mode = @old_parallel_mode;
|
||||
|
||||
--source include/start_slave.inc
|
||||
|
||||
--connection server_1
|
||||
DROP TABLE t;
|
||||
|
||||
--source include/rpl_end.inc
|
@@ -60,7 +60,8 @@ if(!$log_error_)
|
||||
--let SEARCH_FILE=$log_error_
|
||||
--let SEARCH_RANGE=-50000
|
||||
--let SEARCH_PATTERN=using_gtid\(1\), gtid\(\'\'\).*
|
||||
--source include/wait_for_pattern_in_file.inc
|
||||
--let SEARCH_WAIT=FOUND
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
--connection slave
|
||||
--source include/stop_slave.inc
|
||||
@@ -72,7 +73,8 @@ CHANGE MASTER TO MASTER_USE_GTID=no;
|
||||
--let SEARCH_FILE=$log_error_
|
||||
--let SEARCH_RANGE=-50000
|
||||
--let SEARCH_PATTERN=using_gtid\(0\), gtid\(\'\'\).*
|
||||
--source include/wait_for_pattern_in_file.inc
|
||||
--let SEARCH_WAIT=FOUND
|
||||
--source include/search_pattern_in_file.inc
|
||||
CREATE TABLE t (f INT) ENGINE=INNODB;
|
||||
INSERT INTO t VALUES(10);
|
||||
save_master_pos;
|
||||
@@ -90,7 +92,8 @@ CHANGE MASTER TO MASTER_USE_GTID=slave_pos;
|
||||
--let SEARCH_FILE=$log_error_
|
||||
--let SEARCH_RANGE=-50000
|
||||
--let SEARCH_PATTERN=using_gtid\(1\), gtid\(\'0-1-2\'\).*
|
||||
--source include/wait_for_pattern_in_file.inc
|
||||
--let SEARCH_WAIT=FOUND
|
||||
--source include/search_pattern_in_file.inc
|
||||
SET @@SESSION.gtid_domain_id=10;
|
||||
INSERT INTO t VALUES(20);
|
||||
save_master_pos;
|
||||
@@ -108,7 +111,8 @@ CHANGE MASTER TO MASTER_USE_GTID=slave_pos;
|
||||
--let SEARCH_FILE=$log_error_
|
||||
--let SEARCH_RANGE=-50000
|
||||
--let SEARCH_PATTERN=using_gtid\(1\), gtid\(\'0-1-2,10-1-1\'\).*
|
||||
--source include/wait_for_pattern_in_file.inc
|
||||
--let SEARCH_WAIT=FOUND
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
--echo "===== Clean up ====="
|
||||
SET GLOBAL LOG_WARNINGS=@org_log_warnings;
|
||||
|
@@ -0,0 +1,184 @@
|
||||
#
|
||||
# This test ensures that a race condition (reported in MDEV-35109) which
|
||||
# could cause semi-sync transactions binlogging through MYSQL_BIN_LOG::write()
|
||||
# to hang until the semi-sync timeout has been hit, despite the ACK actually
|
||||
# having been received. The problem was that, for a primary configured with
|
||||
# wait_point=AFTER_SYNC, if two threads T1 (binlogging through
|
||||
# MYSQL_BIN_LOG::write()) and T2 were binlogging at the same time, T1 could
|
||||
# accidentally wait for the binlog coordinates of T2. Prior to MDEV-33551,
|
||||
# this only resulted in delayed transactions, because all transactions shared
|
||||
# the same condition variable for ACK signaling. However, with the MDEV-33551
|
||||
# changes, each thread has its own condition variable to signal. So T1 could
|
||||
# wait indefinitely when either:
|
||||
# 1) T1's ACK is received but not T2's when T1 goes into wait_after_sync(),
|
||||
# because the ACK receiver thread has already notified about the T1 ACK,
|
||||
# but T1 was _actually_ waiting on T2's ACK, and therefore tries to wait
|
||||
# (in vain).
|
||||
#
|
||||
# 2) T1 goes to wait_after_sync() before any ACKs have arrived. When T1's ACK
|
||||
# comes in, T1 is woken up; however, sees it needs to wait more (because
|
||||
# it was actually waiting on T2's ACK), and goes to wait again (this time,
|
||||
# in vain).
|
||||
#
|
||||
# Note that the actual cause of T1 waiting on T2's binlog coordinates is when
|
||||
# MYSQL_BIN_LOG::write() would call Repl_semisync_master::wait_after_sync(),
|
||||
# the binlog offset parameter was read as the end of MYSQL_BIN_LOG::log_file,
|
||||
# which is shared among transactions. So if T2 had updated the binary log
|
||||
# _after_ T1 had released LOCK_log, but not yet invoked wait_after_sync(), it
|
||||
# would use the end of the binary log file as the binlog offset, which was that
|
||||
# of T2 (or any future transaction). The patch itself fixes this issue, and
|
||||
# ensures consistency between the binary log coordinates a transaction uses
|
||||
# between report_binlog_update() and wait_after_sync().
|
||||
#
|
||||
# This test reproduces the above race condition, to ensure that T1 can no
|
||||
# longer use T2's binlog coordinates when wait_point=AFTER_SYNC (AFTER_COMMIT
|
||||
# was never affected). That is, because T1 in the above scenario must binlog
|
||||
# through MYSQL_BIN_LOG::write(), it is a DDL. T2 is an MDL that commits
|
||||
# through binlog group commit. We use debug_sync to stop both T1 and T2
|
||||
# after binlogging, reporting their coordinates to the semi-sync cache (i.e.
|
||||
# after report_binlog_update()), and after releasing LOCK_log. Debug_sync is
|
||||
# used on the replica to ensure no ACKs are sent until after both T1 and T2
|
||||
# are paused. Then, T1 and T2 are signaled for wakeup, and both ACKs are sent.
|
||||
# Prior to MDEV-35109 fixes, this results in T1 timing out after the configured
|
||||
# 2 second timeout.
|
||||
#
|
||||
# References:
|
||||
# MDEV-33551: Semi-sync Wait Point AFTER_COMMIT Slow on Workloads with Heavy
|
||||
# Concurrency
|
||||
# MDEV-35109: Semi-sync Replication stalling Primary using
|
||||
# wait_point=AFTER_SYNC
|
||||
#
|
||||
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_debug_sync.inc
|
||||
# Test is format independent
|
||||
--source include/have_binlog_format_row.inc
|
||||
--source include/master-slave.inc
|
||||
|
||||
--connection slave
|
||||
--source include/stop_slave.inc
|
||||
set @old_enabled= @@global.rpl_semi_sync_slave_enabled;
|
||||
set @old_dbug= @@global.debug_dbug;
|
||||
set global rpl_semi_sync_slave_enabled= 1;
|
||||
|
||||
--connection master
|
||||
set @old_enabled= @@global.rpl_semi_sync_master_enabled;
|
||||
set @old_timeout= @@global.rpl_semi_sync_master_timeout;
|
||||
set @old_wait_point= @@global.rpl_semi_sync_master_wait_point;
|
||||
set global rpl_semi_sync_master_enabled= 1;
|
||||
set global rpl_semi_sync_master_timeout= 2000; # 2s
|
||||
set global rpl_semi_sync_master_wait_point= AFTER_SYNC;
|
||||
|
||||
--connection slave
|
||||
--source include/start_slave.inc
|
||||
|
||||
--echo # Ensure slave connection is semi-simulate_delay_semisync_slave_reply
|
||||
--connection master
|
||||
--let $status_var_value= ON
|
||||
--let $status_var= Rpl_semi_sync_master_status
|
||||
--source include/wait_for_status_var.inc
|
||||
--connection slave
|
||||
--let $status_var_value= ON
|
||||
--let $status_var= Rpl_semi_sync_slave_status
|
||||
--source include/wait_for_status_var.inc
|
||||
|
||||
--echo #
|
||||
--echo # Initialize test data
|
||||
--connection master
|
||||
|
||||
# It is simpler to create t1 before using debug_sync on the slave_reply
|
||||
create table t1 (a int) engine=innodb;
|
||||
--source include/save_master_gtid.inc
|
||||
--connection slave
|
||||
--source include/sync_with_master_gtid.inc
|
||||
|
||||
--source include/stop_slave.inc
|
||||
set @@global.debug_dbug="+d,simulate_delay_semisync_slave_reply";
|
||||
--source include/start_slave.inc
|
||||
|
||||
--echo # Ensure connection is semi-sync
|
||||
--connection master
|
||||
--let $status_var_value= ON
|
||||
--let $status_var= Rpl_semi_sync_master_status
|
||||
--source include/wait_for_status_var.inc
|
||||
--connection slave
|
||||
--let $status_var_value= ON
|
||||
--let $status_var= Rpl_semi_sync_slave_status
|
||||
--source include/wait_for_status_var.inc
|
||||
|
||||
--connection master
|
||||
set @old_bgc_count= @@global.binlog_commit_wait_count;
|
||||
set @old_bgc_usec= @@global.binlog_commit_wait_usec;
|
||||
set @@global.binlog_commit_wait_count=1;
|
||||
set @@global.binlog_commit_wait_usec=100000;
|
||||
|
||||
--connection server_1
|
||||
set debug_sync= "commit_after_release_LOCK_log SIGNAL ddl_binlogged WAIT_FOR ddl_cont";
|
||||
--echo # T1 (DDL)
|
||||
--send create table t2 (a int)
|
||||
|
||||
--connect(server_1_sync, localhost, root,,)
|
||||
--connection server_1_sync
|
||||
set debug_sync= "now WAIT_FOR ddl_binlogged";
|
||||
--source include/save_master_gtid.inc
|
||||
|
||||
--connection server_2
|
||||
set debug_sync= "now WAIT_FOR io_thd_at_slave_reply";
|
||||
|
||||
--connection master
|
||||
set debug_sync= "commit_before_get_LOCK_after_binlog_sync SIGNAL mdl_binlogged WAIT_FOR mdl_cont";
|
||||
--echo # T2 (DML)
|
||||
--send insert into t1 values (100);
|
||||
|
||||
--connection server_1_sync
|
||||
set debug_sync= "now WAIT_FOR mdl_binlogged";
|
||||
|
||||
--echo # Both transactions binlogged and released LOCK_log, and are just before
|
||||
--echo # wait_after_sync()
|
||||
set debug_sync= "now SIGNAL ddl_cont";
|
||||
# Ensure ddl_cont is seen before next SIGNAL
|
||||
--let $wait_condition= SELECT count(*)=0 FROM information_schema.processlist WHERE state LIKE "%commit_after_release_LOCK_log%"
|
||||
--source include/wait_condition.inc
|
||||
|
||||
set debug_sync= "now SIGNAL mdl_cont";
|
||||
|
||||
--connection server_2
|
||||
--echo # slave_reply for DDL
|
||||
set debug_sync= "now SIGNAL io_thd_do_reply";
|
||||
--echo # slave_reply for MDL
|
||||
set debug_sync= "now WAIT_FOR io_thd_at_slave_reply";
|
||||
set debug_sync= "now SIGNAL io_thd_do_reply";
|
||||
|
||||
--echo # Reaping MDL..
|
||||
--connection master
|
||||
--reap
|
||||
--echo # ..done
|
||||
|
||||
--echo # Reaping DDL..
|
||||
--connection server_1
|
||||
--reap
|
||||
--echo # ..done
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Cleanup
|
||||
--connection slave
|
||||
--source include/stop_slave.inc
|
||||
set @@global.rpl_semi_sync_slave_enabled= @old_enabled;
|
||||
set @@global.debug_dbug= @old_dbug;
|
||||
--source include/start_slave.inc
|
||||
|
||||
--connection master
|
||||
set @@global.binlog_commit_wait_count= @old_bgc_count;
|
||||
set @@global.binlog_commit_wait_usec= @old_bgc_usec;
|
||||
set @@global.rpl_semi_sync_master_enabled= @old_enabled;
|
||||
set @@global.rpl_semi_sync_master_timeout= @old_timeout;
|
||||
set @@global.rpl_semi_sync_master_wait_point= @old_wait_point;
|
||||
drop table t1, t2;
|
||||
--source include/save_master_gtid.inc
|
||||
|
||||
--connection slave
|
||||
--source include/sync_with_master_gtid.inc
|
||||
|
||||
--source include/rpl_end.inc
|
||||
--echo # End of rpl_semi_sync_after_sync_coord_consistency.test
|
@@ -26,7 +26,7 @@
|
||||
set @old_enabled= @@global.rpl_semi_sync_master_enabled;
|
||||
set @old_timeout= @@global.rpl_semi_sync_master_timeout;
|
||||
set global rpl_semi_sync_master_enabled= 1;
|
||||
set global rpl_semi_sync_master_timeout= 500;
|
||||
set global rpl_semi_sync_master_timeout= 2000; # 2s
|
||||
|
||||
--connection server_2
|
||||
--source include/stop_slave.inc
|
||||
@@ -39,7 +39,9 @@ set global debug_dbug="+d,simulate_delay_semisync_slave_reply";
|
||||
--connection server_3
|
||||
--source include/stop_slave.inc
|
||||
set @old_enabled= @@global.rpl_semi_sync_slave_enabled;
|
||||
set @old_dbug= @@global.debug_dbug;
|
||||
set global rpl_semi_sync_slave_enabled= 1;
|
||||
set global debug_dbug="+d,simulate_delay_semisync_slave_reply";
|
||||
--source include/start_slave.inc
|
||||
|
||||
--echo # Ensure primary recognizes both replicas are semi-sync
|
||||
@@ -55,9 +57,23 @@ if (`SELECT strcmp("$master_ss_status", "ON") != 0`)
|
||||
--die rpl_semi_sync_master_status should be ON to start
|
||||
}
|
||||
|
||||
--connection server_1
|
||||
--connection default
|
||||
--let $init_master_yes_tx= query_get_value(SHOW STATUS LIKE 'rpl_semi_sync_master_yes_tx', Value, 1)
|
||||
create table t1 (a int);
|
||||
--send create table t1 (a int);
|
||||
|
||||
--echo # Ensure both slaves get the event with the need_ack flag set (i.e. one
|
||||
--echo # slave shouldn't be able to receive the event and send an ACK before
|
||||
--echo # the dump thread for the other server prepares the event to send).
|
||||
--connection server_3
|
||||
set debug_sync= "now wait_for io_thd_at_slave_reply";
|
||||
--connection server_2
|
||||
set debug_sync= "now wait_for io_thd_at_slave_reply";
|
||||
--connection server_3
|
||||
set debug_sync= "now signal io_thd_do_reply";
|
||||
|
||||
--connection default
|
||||
--reap
|
||||
|
||||
|
||||
--connection server_2
|
||||
--echo # Verifying server_2 did not send ACK
|
||||
@@ -70,10 +86,6 @@ if (`SELECT $slave1_sent_ack`)
|
||||
|
||||
--connection server_3
|
||||
--echo # Verifying server_3 did send ACK
|
||||
--let $status_var= Rpl_semi_sync_slave_send_ack
|
||||
--let $status_var_comparsion= >
|
||||
--let $status_var_value= 0
|
||||
--source include/wait_for_status_var.inc
|
||||
--let $slave2_sent_ack= query_get_value(SHOW STATUS LIKE 'rpl_semi_sync_slave_send_ack', Value, 1)
|
||||
if (`SELECT NOT $slave2_sent_ack`)
|
||||
{
|
||||
@@ -99,18 +111,22 @@ if (`SELECT $cur_master_yes_tx != ($init_master_yes_tx + 1)`)
|
||||
--die rpl_semi_sync_master_yes_tx should have been incremented by primary
|
||||
}
|
||||
|
||||
--connection server_2
|
||||
set debug_sync= "now signal io_thd_do_reply";
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Cleanup
|
||||
|
||||
--connection server_2
|
||||
--source include/stop_slave.inc
|
||||
set global rpl_semi_sync_slave_enabled= @old_enabled;
|
||||
set global debug_dbug= @old_dbug;
|
||||
--source include/stop_slave.inc
|
||||
|
||||
--connection server_3
|
||||
set global rpl_semi_sync_slave_enabled= @old_enabled;
|
||||
--source include/stop_slave.inc
|
||||
set global rpl_semi_sync_slave_enabled= @old_enabled;
|
||||
set global debug_dbug= @old_dbug;
|
||||
|
||||
--connection server_1
|
||||
set global rpl_semi_sync_master_enabled= @old_enabled;
|
||||
|
@@ -12,10 +12,20 @@
|
||||
# replica after the shutdown
|
||||
# server_3_expect_row_count (int) The number of rows expected on the second
|
||||
# replica after the shutdown
|
||||
# server_2_sync_slave_reply (bool) True if server_2_dbug is configured to use
|
||||
# debug_sync to synchronize the slave reply
|
||||
# (i.e. to pause before the reply)
|
||||
# server_3_sync_slave_reply (bool) True if server_3_dbug is configured to use
|
||||
# debug_sync to synchronize the slave reply
|
||||
# (i.e. to pause before the reply)
|
||||
#
|
||||
|
||||
--connection server_1
|
||||
let $log_error_file= `SELECT @@GLOBAL.log_error`;
|
||||
if (!$n_logged_delayed_shutdown_notes)
|
||||
{
|
||||
let $n_logged_delayed_shutdown_notes= 0;
|
||||
}
|
||||
|
||||
--echo #--
|
||||
--echo #-- Semi-sync Setup
|
||||
@@ -78,19 +88,66 @@ let $status_var= Rpl_semi_sync_master_wait_sessions;
|
||||
let $status_var_value= 1;
|
||||
source include/wait_for_status_var.inc;
|
||||
|
||||
if ($server_2_sync_slave_reply)
|
||||
{
|
||||
--connection server_2
|
||||
set debug_sync= "now wait_for io_thd_at_slave_reply";
|
||||
}
|
||||
if ($server_3_sync_slave_reply)
|
||||
{
|
||||
--connection server_3
|
||||
set debug_sync= "now wait_for io_thd_at_slave_reply";
|
||||
}
|
||||
|
||||
--connection server_1_con2
|
||||
--echo #-- Begin master shutdown
|
||||
SHUTDOWN WAIT FOR ALL SLAVES;
|
||||
--source include/wait_until_disconnected.inc
|
||||
|
||||
# Use server_2 to search error log because 1 is down
|
||||
--connection server_2
|
||||
|
||||
--echo # Waitng for shutdown to be delayed..
|
||||
# Increment the number of notes to find each test case to ensure the pattern is
|
||||
# ours
|
||||
--inc $n_logged_delayed_shutdown_notes
|
||||
let SEARCH_FILE= $log_error_file;
|
||||
let SEARCH_PATTERN=Delaying shutdown to await semi-sync ACK;
|
||||
let SEARCH_WAIT=FOUND $n_logged_delayed_shutdown_notes;
|
||||
source include/search_pattern_in_file.inc;
|
||||
|
||||
if (`SELECT $server_2_sync_slave_reply AND $server_2_expect_row_count`)
|
||||
{
|
||||
--connection server_2
|
||||
set debug_sync= "now signal io_thd_do_reply";
|
||||
}
|
||||
if (`SELECT $server_3_sync_slave_reply AND $server_3_expect_row_count`)
|
||||
{
|
||||
--connection server_3
|
||||
set debug_sync= "now signal io_thd_do_reply";
|
||||
}
|
||||
|
||||
--echo # Reaping transaction..
|
||||
--connection server_1
|
||||
--error 2013
|
||||
--reap
|
||||
--source include/wait_until_disconnected.inc
|
||||
|
||||
--echo # Check logs to ensure shutdown was delayed
|
||||
--let SEARCH_FILE=$log_error_file
|
||||
--let SEARCH_PATTERN=Delaying shutdown to await semi-sync ACK
|
||||
--source include/search_pattern_in_file.inc
|
||||
# Timeout should be hit from prior reap
|
||||
--connection server_2
|
||||
if (`SELECT $server_2_sync_slave_reply AND NOT $server_2_expect_row_count`)
|
||||
{
|
||||
--connection server_2
|
||||
set debug_sync= "now signal io_thd_do_reply";
|
||||
}
|
||||
if (`SELECT $server_3_sync_slave_reply AND NOT $server_3_expect_row_count`)
|
||||
{
|
||||
--connection server_3
|
||||
set debug_sync= "now signal io_thd_do_reply";
|
||||
}
|
||||
|
||||
--echo # Reaping shutdown..
|
||||
--connection server_1_con2
|
||||
--source include/wait_until_disconnected.inc
|
||||
|
||||
--echo # Validate slave data is in correct state
|
||||
--connection server_2
|
||||
|
@@ -113,7 +113,9 @@ while (`SELECT $i <= $slave_last`)
|
||||
--echo # allowed timeout, the primary should delay killing the Ack_thread
|
||||
--echo # until an ACK is received.
|
||||
--echo #
|
||||
--let server_2_sync_slave_reply=1
|
||||
--let server_2_dbug= "+d,simulate_delay_semisync_slave_reply"
|
||||
--let server_3_sync_slave_reply=1
|
||||
--let server_3_dbug= "+d,simulate_delay_semisync_slave_reply"
|
||||
--let semisync_timeout= 1600
|
||||
--let server_2_expect_row_count= 1
|
||||
@@ -125,7 +127,9 @@ while (`SELECT $i <= $slave_last`)
|
||||
--echo # the primary should delay killing the Ack_thread until the
|
||||
--echo # timeout is reached.
|
||||
--echo #
|
||||
--let server_2_sync_slave_reply=0
|
||||
--let server_2_dbug= "+d,corrupt_queue_event,delay_semisync_kill_connection_for_mdev_28141"
|
||||
--let server_3_sync_slave_reply=0
|
||||
--let server_3_dbug= "+d,corrupt_queue_event,delay_semisync_kill_connection_for_mdev_28141"
|
||||
--let semisync_timeout= 500
|
||||
--let server_2_expect_row_count= 0
|
||||
@@ -138,7 +142,9 @@ while (`SELECT $i <= $slave_last`)
|
||||
--echo # primary should delay killing the Ack_thread until it receives an
|
||||
--echo # ACK from the delayed slave.
|
||||
--echo #
|
||||
--let server_2_sync_slave_reply=0
|
||||
--let server_2_dbug= "+d,corrupt_queue_event,delay_semisync_kill_connection_for_mdev_28141"
|
||||
--let server_3_sync_slave_reply=1
|
||||
--let server_3_dbug= "+d,simulate_delay_semisync_slave_reply"
|
||||
--let semisync_timeout= 1600
|
||||
--let server_2_expect_row_count= 0
|
||||
@@ -156,7 +162,9 @@ while (`SELECT $i <= $slave_last`)
|
||||
--echo # sent to kill an active connection. This test case validates that the
|
||||
--echo # slave does not send a `QUIT` in this case.
|
||||
--echo #
|
||||
--let server_2_sync_slave_reply=0
|
||||
--let server_2_dbug= "+d,corrupt_queue_event,delay_semisync_kill_connection_for_mdev_28141"
|
||||
--let server_3_sync_slave_reply=1
|
||||
--let server_3_dbug= "+d,simulate_delay_semisync_slave_reply"
|
||||
--let semisync_timeout= 1600
|
||||
--let server_2_expect_row_count= 0
|
||||
@@ -208,6 +216,9 @@ SET GLOBAL debug_dbug="+d,simulate_delay_semisync_slave_reply";
|
||||
--source include/wait_condition.inc
|
||||
--echo # ..done
|
||||
|
||||
--connection server_2
|
||||
set debug_sync= "now wait_for io_thd_at_slave_reply";
|
||||
|
||||
--disconnect con1
|
||||
|
||||
--connection default
|
||||
@@ -217,12 +228,14 @@ EOF
|
||||
|
||||
--connection con2
|
||||
SHUTDOWN WAIT FOR ALL SLAVES;
|
||||
--source include/wait_until_disconnected.inc
|
||||
|
||||
--echo # Ensure the primary waited for the ACK of the killed thread
|
||||
--let $SEARCH_PATTERN= Delaying shutdown to await semi-sync ACK
|
||||
--let $SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err
|
||||
--source include/search_pattern_in_file.inc
|
||||
--echo # Waitng for shutdown to be delayed..
|
||||
--connection server_2
|
||||
--inc $n_logged_delayed_shutdown_notes
|
||||
let SEARCH_FILE= $log_error_file;
|
||||
let SEARCH_PATTERN=Delaying shutdown to await semi-sync ACK;
|
||||
let SEARCH_WAIT=FOUND $n_logged_delayed_shutdown_notes;
|
||||
source include/search_pattern_in_file.inc;
|
||||
|
||||
--connection default
|
||||
--source include/wait_until_disconnected.inc
|
||||
@@ -230,7 +243,11 @@ SHUTDOWN WAIT FOR ALL SLAVES;
|
||||
--connection server_1
|
||||
--source include/wait_until_disconnected.inc
|
||||
|
||||
--connection con2
|
||||
--source include/wait_until_disconnected.inc
|
||||
|
||||
--connection server_2
|
||||
set debug_sync= "now signal io_thd_do_reply";
|
||||
--let $rpl_allow_error= 1
|
||||
source include/stop_slave.inc;
|
||||
--connection server_3
|
||||
|
Reference in New Issue
Block a user