mirror of
https://github.com/MariaDB/server.git
synced 2025-09-10 03:20:29 +02:00

This is actually an existing problem in the old binlog implementation, and this patch is applicable to old binlog also. The problem is that RESET MASTER can run concurrently with binlog dump threads / connected slaves. This will remove the binlog from under the feet of the reader, which can cause all sorts of strange behaviour. This patch fixes the problem by disallowing to run RESET MASTER when dump threads (or other RESET MASTER or SHOW BINARY LOGS) are running. An error is thrown in this case, user must stop slaves and/or kill dump threads to make the RESET MASTER go through. A slave that connects in the middle of RESET MASTER will wait for it to complete. Fix a lot of test cases to kill any lingering dump threads before doing RESET MASTER, mostly just by sourcing include/kill_binlog_dump_threads.inc. Signed-off-by: Kristian Nielsen <knielsen@knielsen-hq.org>
332 lines
10 KiB
Text
332 lines
10 KiB
Text
--source include/have_innodb.inc
|
|
--source include/have_debug.inc
|
|
--source include/master-slave.inc
|
|
|
|
--echo *** Test that we check against incorrect table definition for mysql.gtid_slave_pos ***
|
|
--connection master
|
|
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB;
|
|
call mtr.add_suppression("Incorrect definition of table mysql.gtid_slave_pos:.*");
|
|
--sync_slave_with_master
|
|
|
|
--connection slave
|
|
--source include/stop_slave.inc
|
|
ALTER TABLE mysql.gtid_slave_pos CHANGE seq_no seq_no VARCHAR(20);
|
|
START SLAVE;
|
|
|
|
--connection master
|
|
INSERT INTO t1 VALUES (1);
|
|
|
|
--connection slave
|
|
CALL mtr.add_suppression("Slave: Failed to open mysql.gtid_slave_pos");
|
|
--let $slave_sql_errno=1944
|
|
--source include/wait_for_slave_sql_error.inc
|
|
--let $rpl_only_running_threads= 1
|
|
--source include/stop_slave.inc
|
|
ALTER TABLE mysql.gtid_slave_pos CHANGE seq_no seq_no BIGINT UNSIGNED NOT NULL;
|
|
ALTER TABLE mysql.gtid_slave_pos DROP PRIMARY KEY;
|
|
ALTER TABLE mysql.gtid_slave_pos ADD PRIMARY KEY (sub_id, domain_id);
|
|
START SLAVE;
|
|
--let $slave_sql_errno=1944
|
|
--source include/wait_for_slave_sql_error.inc
|
|
|
|
--source include/stop_slave.inc
|
|
ALTER TABLE mysql.gtid_slave_pos DROP PRIMARY KEY;
|
|
START SLAVE;
|
|
--let $slave_sql_errno=1944
|
|
--source include/wait_for_slave_sql_error.inc
|
|
|
|
--source include/stop_slave.inc
|
|
ALTER TABLE mysql.gtid_slave_pos ADD PRIMARY KEY (sub_id);
|
|
START SLAVE;
|
|
--let $slave_sql_errno=1944
|
|
--source include/wait_for_slave_sql_error.inc
|
|
|
|
--source include/stop_slave.inc
|
|
ALTER TABLE mysql.gtid_slave_pos DROP PRIMARY KEY;
|
|
ALTER TABLE mysql.gtid_slave_pos ADD PRIMARY KEY (domain_id, sub_id);
|
|
--source include/start_slave.inc
|
|
|
|
--connection master
|
|
--sync_slave_with_master
|
|
|
|
--connection slave
|
|
SELECT * FROM t1;
|
|
|
|
|
|
--echo *** Test that setting @@gtid_domain_id or @@gtid_seq_no is not allowed inside a transaction. ***
|
|
BEGIN;
|
|
INSERT INTO t1 VALUES (100);
|
|
--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_GTID_DOMAIN_ID_SEQ_NO
|
|
SET SESSION gtid_domain_id= 100;
|
|
--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_GTID_DOMAIN_ID_SEQ_NO
|
|
SET SESSION gtid_seq_no= 100;
|
|
SET @old_domain= @@GLOBAL.gtid_domain_id;
|
|
SET GLOBAL gtid_domain_id= 100;
|
|
SELECT @@SESSION.gtid_domain_id;
|
|
SET GLOBAL gtid_domain_id= @old_domain;
|
|
INSERT INTO t1 VALUES (101);
|
|
SELECT * FROM t1 ORDER BY a;
|
|
ROLLBACK;
|
|
SELECT * FROM t1 ORDER BY a;
|
|
|
|
# MDEV-34049: Parallel access to temptable in different domain_id in parallel replication
|
|
#
|
|
# Temporary tables must be prevented from being accessed from multiple threads
|
|
# at the same time in parallel replication. Withon one domain_id, this is done
|
|
# by running wait_for_prior_commit() before accessing a temporary table. To
|
|
# prevent the same temporary table from being accessed in parallel from two
|
|
# domains in out-of-order parallel replication, an error must be raised on
|
|
# attempt to change the gtid_domain_id while temporary tables are in use in
|
|
# a session and binlogged. In row-based binlogging, temporary tables are not
|
|
# binlogged, so gtid_domain_id can be freely changed.
|
|
SET @old_mode= @@SESSION.binlog_format;
|
|
SET SESSION binlog_format= row;
|
|
SET SESSION gtid_domain_id= 200;
|
|
CREATE TEMPORARY TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
|
|
SET SESSION gtid_domain_id= 0;
|
|
BEGIN;
|
|
INSERT INTO t2 VALUES (200);
|
|
INSERT INTO t1 SELECT * FROM t2;
|
|
COMMIT;
|
|
SET SESSION gtid_domain_id= 201;
|
|
SET SESSION gtid_domain_id= 0;
|
|
DELETE FROM t1 WHERE a=200;
|
|
SET SESSION gtid_domain_id= 202;
|
|
DROP TEMPORARY TABLE t2;
|
|
|
|
SET SESSION binlog_format= mixed;
|
|
SET SESSION gtid_domain_id= 0;
|
|
CREATE TEMPORARY TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
|
|
INSERT INTO t2 VALUES (1);
|
|
SET SESSION gtid_domain_id= 0;
|
|
--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_GTID_DOMAIN_ID_SEQ_NO
|
|
SET SESSION gtid_domain_id= 204;
|
|
SET SESSION binlog_format=statement;
|
|
INSERT INTO t2 VALUES (2);
|
|
--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_GTID_DOMAIN_ID_SEQ_NO
|
|
SET SESSION gtid_domain_id= 205;
|
|
DROP TEMPORARY TABLE t2;
|
|
SET SESSION gtid_domain_id= @old_domain;
|
|
SET SESSION binlog_format= @old_mode;
|
|
|
|
|
|
--echo *** Test requesting an explicit GTID position that conflicts with newer GTIDs of our own in the binlog. ***
|
|
--connection slave
|
|
--source include/stop_slave.inc
|
|
|
|
--connection master
|
|
--source include/kill_binlog_dump_threads.inc
|
|
RESET MASTER;
|
|
# This insert will be GTID 0-1-1
|
|
INSERT INTO t1 VALUES (2);
|
|
# And this will be GTID 0-1-2
|
|
INSERT INTO t1 VALUES (4);
|
|
--source include/save_master_gtid.inc
|
|
|
|
--connection slave
|
|
SET sql_log_bin = 0;
|
|
INSERT INTO t1 VALUES (2);
|
|
SET sql_log_bin = 1;
|
|
INSERT INTO t1 VALUES (3);
|
|
|
|
CHANGE MASTER TO master_use_gtid=current_pos;
|
|
# Most not change @@GLOBAL.gtid_slave_pos in the middle of a transaction.
|
|
BEGIN;
|
|
--error ER_CANT_DO_THIS_DURING_AN_TRANSACTION
|
|
SET GLOBAL gtid_slave_pos = "100-100-100";
|
|
INSERT INTO t1 VALUES (100);
|
|
--error ER_CANT_DO_THIS_DURING_AN_TRANSACTION
|
|
SET GLOBAL gtid_slave_pos = "100-100-100";
|
|
ROLLBACK;
|
|
|
|
# In gtid non-strict mode, we get warnings for setting @@gtid_slave_pos back
|
|
# to earlier than what is in the binlog. In strict mode, we get an error.
|
|
SET GLOBAL gtid_strict_mode= 1;
|
|
--error ER_MASTER_GTID_POS_CONFLICTS_WITH_BINLOG
|
|
SET GLOBAL gtid_slave_pos = "0-1-1";
|
|
--error ER_MASTER_GTID_POS_MISSING_DOMAIN
|
|
SET GLOBAL gtid_slave_pos = "";
|
|
SET GLOBAL gtid_strict_mode= 0;
|
|
SET GLOBAL gtid_slave_pos = "0-1-1";
|
|
SET GLOBAL gtid_slave_pos = "";
|
|
RESET MASTER;
|
|
SET GLOBAL gtid_slave_pos = "0-1-1";
|
|
|
|
START SLAVE;
|
|
--source include/sync_with_master_gtid.inc
|
|
SELECT * FROM t1 ORDER BY a;
|
|
|
|
--echo *** MDEV-4688: Empty value of @@GLOBAL.gtid_slave_pos ***
|
|
# The problem was that record_gtid() deleted too much of the in-memory state,
|
|
# leaving the state empty until after commit when we add the newly committed
|
|
# GTID. Test this by forcing an error after the delete of the old data but
|
|
# before the add of new data.
|
|
|
|
--source include/stop_slave.inc
|
|
|
|
--connection master
|
|
# This will be GTID 0-1-3
|
|
INSERT INTO t1 VALUES (5);
|
|
--source include/save_master_gtid.inc
|
|
|
|
--connection slave
|
|
SET @old_dbug= @@GLOBAL.debug_dbug;
|
|
SET GLOBAL debug_dbug="+d,dummy_disable_default_dbug_output";
|
|
SET GLOBAL debug_dbug="+d,gtid_fail_after_record_gtid";
|
|
SET sql_log_bin=0;
|
|
CALL mtr.add_suppression('Got error 131 "Command not supported by the engine" during COMMIT');
|
|
SET sql_log_bin=1;
|
|
START SLAVE;
|
|
--let $slave_sql_errno= 1180
|
|
--source include/wait_for_slave_sql_error.inc
|
|
# The bug was that @@GLOBAL.gtid_slave_pos was empty here.
|
|
SELECT @@GLOBAL.gtid_slave_pos;
|
|
SELECT * FROM t1 ORDER BY a;
|
|
SET GLOBAL debug_dbug= @old_dbug;
|
|
START SLAVE SQL_THREAD;
|
|
--source include/sync_with_master_gtid.inc
|
|
SELECT * FROM t1 ORDER BY a;
|
|
|
|
|
|
--echo *** Test slave requesting a GTID that is not present in the master's binlog ***
|
|
--source include/stop_slave.inc
|
|
SET GLOBAL gtid_slave_pos = "0-1-4";
|
|
START SLAVE;
|
|
|
|
SET sql_log_bin=0;
|
|
CALL mtr.add_suppression("Got fatal error .* from master when reading data from binary log: 'Error: connecting slave requested to start from GTID .*, which is not in the master's binlog'");
|
|
SET sql_log_bin=1;
|
|
--let $slave_io_errno= 1236
|
|
--source include/wait_for_slave_io_error.inc
|
|
--let $status_items= Slave_IO_State, Last_IO_Errno, Last_IO_Error, Using_Gtid
|
|
--source include/show_slave_status.inc
|
|
|
|
--let $rpl_only_running_threads= 1
|
|
--source include/stop_slave.inc
|
|
SET GLOBAL gtid_slave_pos = "0-1-3";
|
|
START SLAVE;
|
|
--source include/wait_for_slave_to_start.inc
|
|
|
|
--connection master
|
|
INSERT INTO t1 VALUES (6);
|
|
--source include/save_master_gtid.inc
|
|
|
|
--connection slave
|
|
--source include/sync_with_master_gtid.inc
|
|
SELECT * FROM t1 ORDER BY a;
|
|
|
|
|
|
--echo *** MDEV-4278: Slave does not detect that master is not GTID-aware ***
|
|
|
|
--connection slave
|
|
--source include/stop_slave.inc
|
|
|
|
--connection master
|
|
SET @old_dbug= @@global.DEBUG_DBUG;
|
|
SET GLOBAL debug_dbug="+d,simulate_non_gtid_aware_master";
|
|
|
|
--connection slave
|
|
START SLAVE;
|
|
--let $slave_io_errno= 1233
|
|
--source include/wait_for_slave_io_error.inc
|
|
|
|
--connection master
|
|
SET GLOBAL debug_dbug= @old_dbug;
|
|
INSERT INTO t1 VALUES (7);
|
|
--save_master_pos
|
|
|
|
--connection slave
|
|
START SLAVE;
|
|
--sync_with_master
|
|
SET sql_log_bin=0;
|
|
CALL mtr.add_suppression("The slave I/O thread stops because master does not support MariaDB global transaction id");
|
|
SET sql_log_bin=1;
|
|
|
|
|
|
--echo *** Test error during record_gtid() (non-xid cases) ***
|
|
|
|
--connection slave
|
|
--source include/stop_slave.inc
|
|
|
|
--connection master
|
|
CREATE TABLE t2 (a INT) ENGINE=MyISAM;
|
|
INSERT INTO t2 VALUES (1);
|
|
--save_master_pos
|
|
|
|
--connection slave
|
|
SET @old_dbug= @@global.DEBUG_DBUG;
|
|
SET GLOBAL debug_dbug="+d,gtid_inject_record_gtid";
|
|
|
|
START SLAVE;
|
|
--let $slave_sql_errno= 1942
|
|
--source include/wait_for_slave_sql_error.inc
|
|
|
|
SET GLOBAL debug_dbug= @old_dbug;
|
|
|
|
START SLAVE SQL_THREAD;
|
|
--sync_with_master
|
|
|
|
SELECT * FROM t2;
|
|
SET sql_log_bin=0;
|
|
CALL mtr.add_suppression("Slave: Could not update replication slave gtid state");
|
|
SET sql_log_bin=1;
|
|
|
|
|
|
--echo *** MDEV-4906: When event apply fails, next SQL thread start erroneously commits the failing GTID to gtid_slave_pos ***
|
|
|
|
--connection slave
|
|
--source include/stop_slave.inc
|
|
SET sql_log_bin=0;
|
|
DELETE FROM t2;
|
|
SET sql_log_bin=1;
|
|
SET @old_format=@@binlog_format;
|
|
SET GLOBAL binlog_format='row';
|
|
--source include/start_slave.inc
|
|
|
|
--connection master
|
|
SET @old_format=@@binlog_format;
|
|
SET binlog_format='row';
|
|
--let $gtid_pos1=`SELECT @@GLOBAL.gtid_binlog_pos`
|
|
DELETE FROM t2;
|
|
SET binlog_format=@old_format;
|
|
--save_master_pos
|
|
|
|
--connection slave
|
|
--let $slave_sql_errno= 1032
|
|
--source include/wait_for_slave_sql_error.inc
|
|
# Disable query to avoid result file update if precise GTID value changes.
|
|
--disable_query_log
|
|
SET @x=@@GLOBAL.gtid_slave_pos;
|
|
eval SELECT IF(@x='$gtid_pos1', "OK", CONCAT("ERROR: expected $gtid_pos1 got ", @x)) AS result;
|
|
--enable_query_log
|
|
|
|
# The bug was that upon restarting the SQL thread, the GTID for the
|
|
# failing event group was not cleared, so we would update it in the
|
|
# gtid_slave_pos as part of the first rotate event, corrupting the
|
|
# replication.
|
|
STOP SLAVE IO_THREAD;
|
|
START SLAVE;
|
|
--let $slave_sql_errno= 1032
|
|
--source include/wait_for_slave_sql_error.inc
|
|
# Disable query to avoid result file update if precise GTID value changes.
|
|
--disable_query_log
|
|
SET @x=@@GLOBAL.gtid_slave_pos;
|
|
eval SELECT IF(@x='$gtid_pos1', "OK", CONCAT("ERROR: expected $gtid_pos1 got ", @x)) AS result;
|
|
--enable_query_log
|
|
|
|
STOP SLAVE IO_THREAD;
|
|
SET sql_log_bin=0;
|
|
INSERT INTO t2 VALUES (1);
|
|
CALL mtr.add_suppression("Slave: Can't find record in 't2' Error_code: 1032");
|
|
SET sql_log_bin=1;
|
|
--source include/start_slave.inc
|
|
--sync_with_master
|
|
SET GLOBAL binlog_format=@old_format;
|
|
|
|
--connection master
|
|
DROP TABLE t1;
|
|
DROP TABLE t2;
|
|
|
|
call mtr.add_suppression("Can't find record in 't2'");
|
|
|
|
--source include/rpl_end.inc
|