Merge 10.2 into 10.3, except MDEV-25682
This commit is contained in:
commit
ca3f497564
@ -770,7 +770,7 @@ call p_verify_status_increment(2, 0, 2, 0);
|
||||
commit;
|
||||
call p_verify_status_increment(0, 0, 0, 0);
|
||||
check table t1, t2, t3;
|
||||
call p_verify_status_increment(6, 0, 6, 0);
|
||||
call p_verify_status_increment(4, 0, 4, 0);
|
||||
commit;
|
||||
call p_verify_status_increment(0, 0, 0, 0);
|
||||
drop view v1;
|
||||
|
@ -139,7 +139,7 @@ sub do_args($$$$$) {
|
||||
my $v = $debuggers{$k};
|
||||
|
||||
# on windows mtr args are quoted (for system), otherwise not (for exec)
|
||||
sub quote($) { $_[0] =~ / / ? "\"$_[0]\"" : $_[0] }
|
||||
sub quote($) { $_[0] =~ /[; ]/ ? "\"$_[0]\"" : $_[0] }
|
||||
sub unquote($) { $_[0] =~ s/^"(.*)"$/$1/; $_[0] }
|
||||
sub quote_from_mtr($) { IS_WINDOWS() ? $_[0] : quote($_[0]) }
|
||||
sub unquote_for_mtr($) { IS_WINDOWS() ? $_[0] : unquote($_[0]) }
|
||||
|
@ -874,7 +874,7 @@ Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
test.t2 check status OK
|
||||
test.t3 check status OK
|
||||
call p_verify_status_increment(6, 0, 6, 0);
|
||||
call p_verify_status_increment(4, 0, 4, 0);
|
||||
SUCCESS
|
||||
|
||||
commit;
|
||||
|
4
mysql-test/main/mdev_22370.result
Normal file
4
mysql-test/main/mdev_22370.result
Normal file
@ -0,0 +1,4 @@
|
||||
connect con1,localhost,root,,;
|
||||
SET DEBUG_DBUG='+d,mark_busy_mdev_22370';
|
||||
FLUSH TABLES WITH READ LOCK;
|
||||
connection default;
|
17
mysql-test/main/mdev_22370.test
Normal file
17
mysql-test/main/mdev_22370.test
Normal file
@ -0,0 +1,17 @@
|
||||
#
|
||||
# MDEV-22370 safe_mutex: Trying to lock uninitialized mutex at
|
||||
# /data/src/10.4-bug/sql/rpl_parallel.cc, line 470 upon shutdown during FTWRL
|
||||
#
|
||||
# Purpose of this test case to test crash while FTWRL and shutdown is in race
|
||||
# condition
|
||||
# Shutdown can execute first and destroy the mutex making mutex_lock in pool_mark_busy
|
||||
# to crash
|
||||
|
||||
--source include/have_debug.inc
|
||||
--connect (con1,localhost,root,,)
|
||||
SET DEBUG_DBUG='+d,mark_busy_mdev_22370';
|
||||
--send
|
||||
FLUSH TABLES WITH READ LOCK;
|
||||
|
||||
--connection default
|
||||
--source include/restart_mysqld.inc
|
40
mysql-test/suite/binlog/r/binlog_admin_cmd_kill.result
Normal file
40
mysql-test/suite/binlog/r/binlog_admin_cmd_kill.result
Normal file
@ -0,0 +1,40 @@
|
||||
#
|
||||
# Kill OPTIMIZE command prior to table modification
|
||||
#
|
||||
RESET MASTER;
|
||||
CREATE TABLE t1 (f INT) ENGINE=INNODB;
|
||||
CREATE TABLE t2 (f INT) ENGINE=INNODB;
|
||||
connect con1,127.0.0.1,root,,test,$MASTER_MYPORT,;
|
||||
connection con1;
|
||||
SET debug_sync='admin_command_kill_before_modify SIGNAL ready_to_be_killed WAIT_FOR master_cont';
|
||||
OPTIMIZE TABLE t1,t2;
|
||||
connection default;
|
||||
SET debug_sync='now WAIT_FOR ready_to_be_killed';
|
||||
KILL THD_ID;
|
||||
SET debug_sync = 'reset';
|
||||
disconnect con1;
|
||||
include/show_binlog_events.inc
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 # Gtid # # GTID #-#-#
|
||||
master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (f INT) ENGINE=INNODB
|
||||
master-bin.000001 # Gtid # # GTID #-#-#
|
||||
master-bin.000001 # Query # # use `test`; CREATE TABLE t2 (f INT) ENGINE=INNODB
|
||||
DROP TABLE t1,t2;
|
||||
FLUSH LOGS;
|
||||
#
|
||||
# Kill OPTIMIZE command after table modification
|
||||
#
|
||||
CREATE TABLE t1 (f INT) ENGINE=INNODB;
|
||||
CREATE TABLE t2 (f INT) ENGINE=INNODB;
|
||||
connect con1,127.0.0.1,root,,test,$MASTER_MYPORT,;
|
||||
connection con1;
|
||||
SET debug_sync='admin_command_kill_after_modify SIGNAL ready_to_be_killed WAIT_FOR master_cont';
|
||||
OPTIMIZE TABLE t1,t2;
|
||||
connection default;
|
||||
SET debug_sync='now WAIT_FOR ready_to_be_killed';
|
||||
KILL THD_ID;
|
||||
SET debug_sync = 'reset';
|
||||
disconnect con1;
|
||||
DROP TABLE t1,t2;
|
||||
FLUSH LOGS;
|
||||
FOUND 1 /OPTIMIZE TABLE t1,t2/ in mysqlbinlog.out
|
95
mysql-test/suite/binlog/t/binlog_admin_cmd_kill.test
Normal file
95
mysql-test/suite/binlog/t/binlog_admin_cmd_kill.test
Normal file
@ -0,0 +1,95 @@
|
||||
# ==== Purpose ====
|
||||
#
|
||||
# Test verifies that when an admin command execution is interrupted by KILL
|
||||
# command it should stop its execution. The admin command in binary log should
|
||||
# contain only the list of tables which have successfully executed admin
|
||||
# command prior to kill.
|
||||
#
|
||||
# ==== Implementation ====
|
||||
#
|
||||
# Steps:
|
||||
# 0 - Create two table t1,t2.
|
||||
# 1 - Execute OPTIMIZE TABLE t1,t2 command.
|
||||
# 2 - Using debug sync mechanism kill OPTIMIZE TABLE command at a stage
|
||||
# where it has not optimized any table.
|
||||
# 3 - Check that OPTIMIZE TABLE command is not written to binary log.
|
||||
# 4 - Using debug sync mechanism hold the execution of OPTIMIZE TABLE after
|
||||
# t1 table optimization. Now kill the OPTIMIZE TABLE command.
|
||||
# 5 - Observe the binlog output, the OPTIMIZE TABLE command should display `t1,t2`.
|
||||
# 6 - Please note that, we binlog the entire query even if at least one
|
||||
# table is modified as admin commands are safe to replicate and they will
|
||||
# not make the slave to diverge.
|
||||
#
|
||||
# ==== References ====
|
||||
#
|
||||
# MDEV-22530: Aborting OPTIMIZE TABLE still logs in binary log and replicates to the Slave server.
|
||||
#
|
||||
--source include/have_log_bin.inc
|
||||
--source include/have_debug.inc
|
||||
--source include/have_debug_sync.inc
|
||||
--source include/have_innodb.inc
|
||||
|
||||
--echo #
|
||||
--echo # Kill OPTIMIZE command prior to table modification
|
||||
--echo #
|
||||
RESET MASTER;
|
||||
|
||||
CREATE TABLE t1 (f INT) ENGINE=INNODB;
|
||||
CREATE TABLE t2 (f INT) ENGINE=INNODB;
|
||||
|
||||
--connect(con1,127.0.0.1,root,,test,$MASTER_MYPORT,)
|
||||
--connection con1
|
||||
SET debug_sync='admin_command_kill_before_modify SIGNAL ready_to_be_killed WAIT_FOR master_cont';
|
||||
--send OPTIMIZE TABLE t1,t2
|
||||
|
||||
--connection default
|
||||
SET debug_sync='now WAIT_FOR ready_to_be_killed';
|
||||
--let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%OPTIMIZE TABLE %'`
|
||||
|
||||
# Now kill.
|
||||
--replace_result $thd_id THD_ID
|
||||
eval KILL $thd_id;
|
||||
|
||||
SET debug_sync = 'reset';
|
||||
--disconnect con1
|
||||
|
||||
--source include/show_binlog_events.inc
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
FLUSH LOGS;
|
||||
|
||||
--echo #
|
||||
--echo # Kill OPTIMIZE command after table modification
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (f INT) ENGINE=INNODB;
|
||||
CREATE TABLE t2 (f INT) ENGINE=INNODB;
|
||||
|
||||
--connect(con1,127.0.0.1,root,,test,$MASTER_MYPORT,)
|
||||
--connection con1
|
||||
SET debug_sync='admin_command_kill_after_modify SIGNAL ready_to_be_killed WAIT_FOR master_cont';
|
||||
--send OPTIMIZE TABLE t1,t2
|
||||
|
||||
--connection default
|
||||
SET debug_sync='now WAIT_FOR ready_to_be_killed';
|
||||
--let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%OPTIMIZE TABLE %'`
|
||||
|
||||
# Now kill.
|
||||
--replace_result $thd_id THD_ID
|
||||
eval KILL $thd_id;
|
||||
|
||||
SET debug_sync = 'reset';
|
||||
--disconnect con1
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
|
||||
FLUSH LOGS;
|
||||
|
||||
--let $MYSQLD_DATADIR= `select @@datadir`
|
||||
--exec $MYSQL_BINLOG $MYSQLD_DATADIR/$binlog_file > $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
|
||||
|
||||
--let SEARCH_PATTERN= OPTIMIZE TABLE t1,t2
|
||||
--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
|
77
mysql-test/suite/rpl/r/rpl_mark_optimize_tbl_ddl.result
Normal file
77
mysql-test/suite/rpl/r/rpl_mark_optimize_tbl_ddl.result
Normal file
@ -0,0 +1,77 @@
|
||||
include/rpl_init.inc [topology=1->2]
|
||||
connection server_1;
|
||||
FLUSH TABLES;
|
||||
ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
|
||||
connection server_2;
|
||||
SET @save_slave_parallel_threads= @@GLOBAL.slave_parallel_threads;
|
||||
SET @save_slave_parallel_mode= @@GLOBAL.slave_parallel_mode;
|
||||
include/stop_slave.inc
|
||||
SET GLOBAL slave_parallel_threads=2;
|
||||
SET GLOBAL slave_parallel_mode=optimistic;
|
||||
include/start_slave.inc
|
||||
connection server_1;
|
||||
CREATE TABLE t1(a INT) ENGINE=INNODB;
|
||||
OPTIMIZE TABLE t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
|
||||
test.t1 optimize status OK
|
||||
INSERT INTO t1 VALUES(1);
|
||||
INSERT INTO t1 SELECT 1+a FROM t1;
|
||||
INSERT INTO t1 SELECT 2+a FROM t1;
|
||||
connection server_2;
|
||||
#
|
||||
# Verify that following admin commands are marked as ddl
|
||||
# 'OPTIMIZE TABLE', 'REPAIR TABLE' and 'ANALYZE TABLE'
|
||||
#
|
||||
connection server_1;
|
||||
OPTIMIZE TABLE t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
|
||||
test.t1 optimize status OK
|
||||
REPAIR TABLE t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 repair note The storage engine for the table doesn't support repair
|
||||
ANALYZE TABLE t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status OK
|
||||
FLUSH LOGS;
|
||||
FOUND 1 /GTID 0-1-8 ddl/ in mysqlbinlog.out
|
||||
FOUND 1 /GTID 0-1-9 ddl/ in mysqlbinlog.out
|
||||
FOUND 1 /GTID 0-1-10 ddl/ in mysqlbinlog.out
|
||||
#
|
||||
# Clean up
|
||||
#
|
||||
DROP TABLE t1;
|
||||
connection server_2;
|
||||
FLUSH LOGS;
|
||||
#
|
||||
# Check that ALTER TABLE commands with ANALYZE, OPTIMIZE and REPAIR on
|
||||
# partitions will be marked as DDL in binary log.
|
||||
#
|
||||
connection server_1;
|
||||
CREATE TABLE t1(id INT) PARTITION BY RANGE (id) (PARTITION p0 VALUES LESS THAN (100),
|
||||
PARTITION pmax VALUES LESS THAN (MAXVALUE));
|
||||
INSERT INTO t1 VALUES (1), (10), (100), (1000);
|
||||
ALTER TABLE t1 ANALYZE PARTITION p0;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status OK
|
||||
ALTER TABLE t1 OPTIMIZE PARTITION p0;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 optimize status OK
|
||||
ALTER TABLE t1 REPAIR PARTITION p0;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 repair status OK
|
||||
FLUSH LOGS;
|
||||
FOUND 1 /GTID 0-1-14 ddl/ in mysqlbinlog.out
|
||||
FOUND 1 /GTID 0-1-15 ddl/ in mysqlbinlog.out
|
||||
FOUND 1 /GTID 0-1-16 ddl/ in mysqlbinlog.out
|
||||
#
|
||||
# Clean up
|
||||
#
|
||||
DROP TABLE t1;
|
||||
connection server_2;
|
||||
include/stop_slave.inc
|
||||
SET GLOBAL slave_parallel_threads= @save_slave_parallel_threads;
|
||||
SET GLOBAL slave_parallel_mode= @save_slave_parallel_mode;
|
||||
include/start_slave.inc
|
||||
include/rpl_end.inc
|
79
mysql-test/suite/rpl/r/rpl_slave_shutdown_mdev20821.result
Normal file
79
mysql-test/suite/rpl/r/rpl_slave_shutdown_mdev20821.result
Normal file
@ -0,0 +1,79 @@
|
||||
include/rpl_init.inc [topology=1->3]
|
||||
connection server_3;
|
||||
set default_master_connection = '';
|
||||
include/start_slave.inc
|
||||
Warnings:
|
||||
Note 1254 Slave is already running
|
||||
set default_master_connection = 'm2';
|
||||
change master to master_host='127.0.0.1', master_port=SERVER_MYPORT_2, master_user='root', master_use_gtid=slave_pos;
|
||||
include/start_slave.inc
|
||||
select @@global.slave_parallel_workers as two;
|
||||
two
|
||||
2
|
||||
connection server_3;
|
||||
SHUTDOWN;
|
||||
connection server_3;
|
||||
connection server_3;
|
||||
connection server_1;
|
||||
create table t1 (i int primary key) engine=Innodb;
|
||||
connection server_2;
|
||||
create table t2 (i int primary key) engine=Innodb;
|
||||
connection server_3;
|
||||
set default_master_connection = '';
|
||||
include/start_slave.inc
|
||||
Warnings:
|
||||
Note 1254 Slave is already running
|
||||
set default_master_connection = 'm2';
|
||||
include/start_slave.inc
|
||||
Warnings:
|
||||
Note 1254 Slave is already running
|
||||
connection server_2;
|
||||
insert into t2 values (1);
|
||||
connection server_3;
|
||||
connection server_1;
|
||||
insert into t1 values (1);
|
||||
connection server_3;
|
||||
connection server_3;
|
||||
SHUTDOWN;
|
||||
connection server_3;
|
||||
connection server_3;
|
||||
connection server_3;
|
||||
set default_master_connection = '';
|
||||
include/start_slave.inc
|
||||
Warnings:
|
||||
Note 1254 Slave is already running
|
||||
set default_master_connection = 'm2';
|
||||
include/start_slave.inc
|
||||
Warnings:
|
||||
Note 1254 Slave is already running
|
||||
connect conn_block_server3, 127.0.0.1, root,, test, $SERVER_MYPORT_3,;
|
||||
begin;
|
||||
insert into t1 values (2);
|
||||
insert into t2 values (2);
|
||||
connection server_1;
|
||||
insert into t1 values (2);
|
||||
connection server_2;
|
||||
insert into t2 values (2);
|
||||
connection server_3;
|
||||
SHUTDOWN;
|
||||
connection server_3;
|
||||
connection server_3;
|
||||
connection server_3;
|
||||
set default_master_connection = '';
|
||||
include/start_slave.inc
|
||||
Warnings:
|
||||
Note 1254 Slave is already running
|
||||
set default_master_connection = 'm2';
|
||||
include/start_slave.inc
|
||||
Warnings:
|
||||
Note 1254 Slave is already running
|
||||
connection server_1;
|
||||
drop table t1;
|
||||
connection server_2;
|
||||
drop table t2;
|
||||
connection server_3;
|
||||
set default_master_connection = 'm2';
|
||||
include/stop_slave.inc
|
||||
RESET SLAVE ALL;
|
||||
set default_master_connection = '';
|
||||
include/rpl_end.inc
|
142
mysql-test/suite/rpl/t/rpl_mark_optimize_tbl_ddl.test
Normal file
142
mysql-test/suite/rpl/t/rpl_mark_optimize_tbl_ddl.test
Normal file
@ -0,0 +1,142 @@
|
||||
# ==== Purpose ====
|
||||
#
|
||||
# Test verifies that there is no deadlock or assertion in
|
||||
# slave_parallel_mode=optimistic configuration while applying admin command
|
||||
# like 'OPTIMIZE TABLE', 'REPAIR TABLE' and 'ANALYZE TABLE'.
|
||||
#
|
||||
# ==== Implementation ====
|
||||
#
|
||||
# Steps:
|
||||
# 0 - Create a table, execute OPTIMIZE TABLE command on the table followed
|
||||
# by some DMLS.
|
||||
# 1 - No assert should happen on slave server.
|
||||
# 2 - Assert that 'OPTIMIZE TABLE', 'REPAIR TABLE' and 'ANALYZE TABLE' are
|
||||
# marked as 'DDL' in the binary log.
|
||||
#
|
||||
# ==== References ====
|
||||
#
|
||||
# MDEV-17515: GTID Replication in optimistic mode deadlock
|
||||
#
|
||||
--source include/have_partition.inc
|
||||
--source include/have_innodb.inc
|
||||
--let $rpl_topology=1->2
|
||||
--source include/rpl_init.inc
|
||||
|
||||
--connection server_1
|
||||
FLUSH TABLES;
|
||||
ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
|
||||
|
||||
--connection server_2
|
||||
SET @save_slave_parallel_threads= @@GLOBAL.slave_parallel_threads;
|
||||
SET @save_slave_parallel_mode= @@GLOBAL.slave_parallel_mode;
|
||||
--source include/stop_slave.inc
|
||||
SET GLOBAL slave_parallel_threads=2;
|
||||
SET GLOBAL slave_parallel_mode=optimistic;
|
||||
--source include/start_slave.inc
|
||||
|
||||
--connection server_1
|
||||
CREATE TABLE t1(a INT) ENGINE=INNODB;
|
||||
OPTIMIZE TABLE t1;
|
||||
INSERT INTO t1 VALUES(1);
|
||||
INSERT INTO t1 SELECT 1+a FROM t1;
|
||||
INSERT INTO t1 SELECT 2+a FROM t1;
|
||||
--save_master_pos
|
||||
|
||||
--connection server_2
|
||||
--sync_with_master
|
||||
|
||||
--echo #
|
||||
--echo # Verify that following admin commands are marked as ddl
|
||||
--echo # 'OPTIMIZE TABLE', 'REPAIR TABLE' and 'ANALYZE TABLE'
|
||||
--echo #
|
||||
--connection server_1
|
||||
|
||||
OPTIMIZE TABLE t1;
|
||||
--let optimize_gtid= `SELECT @@GLOBAL.gtid_binlog_pos`
|
||||
|
||||
REPAIR TABLE t1;
|
||||
--let repair_gtid= `SELECT @@GLOBAL.gtid_binlog_pos`
|
||||
|
||||
ANALYZE TABLE t1;
|
||||
--let analyze_gtid= `SELECT @@GLOBAL.gtid_binlog_pos`
|
||||
|
||||
let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
|
||||
FLUSH LOGS;
|
||||
|
||||
--let $MYSQLD_DATADIR= `select @@datadir`
|
||||
--exec $MYSQL_BINLOG $MYSQLD_DATADIR/$binlog_file > $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
|
||||
|
||||
--let SEARCH_PATTERN= GTID $optimize_gtid ddl
|
||||
--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
--let SEARCH_PATTERN= GTID $repair_gtid ddl
|
||||
--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
--let SEARCH_PATTERN= GTID $analyze_gtid ddl
|
||||
--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
--echo #
|
||||
--echo # Clean up
|
||||
--echo #
|
||||
DROP TABLE t1;
|
||||
--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
|
||||
--save_master_pos
|
||||
|
||||
--connection server_2
|
||||
--sync_with_master
|
||||
FLUSH LOGS;
|
||||
|
||||
--echo #
|
||||
--echo # Check that ALTER TABLE commands with ANALYZE, OPTIMIZE and REPAIR on
|
||||
--echo # partitions will be marked as DDL in binary log.
|
||||
--echo #
|
||||
--connection server_1
|
||||
CREATE TABLE t1(id INT) PARTITION BY RANGE (id) (PARTITION p0 VALUES LESS THAN (100),
|
||||
PARTITION pmax VALUES LESS THAN (MAXVALUE));
|
||||
INSERT INTO t1 VALUES (1), (10), (100), (1000);
|
||||
|
||||
ALTER TABLE t1 ANALYZE PARTITION p0;
|
||||
--let analyze_gtid= `SELECT @@GLOBAL.gtid_binlog_pos`
|
||||
|
||||
ALTER TABLE t1 OPTIMIZE PARTITION p0;
|
||||
--let optimize_gtid= `SELECT @@GLOBAL.gtid_binlog_pos`
|
||||
|
||||
ALTER TABLE t1 REPAIR PARTITION p0;
|
||||
--let repair_gtid= `SELECT @@GLOBAL.gtid_binlog_pos`
|
||||
|
||||
let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
|
||||
FLUSH LOGS;
|
||||
|
||||
--exec $MYSQL_BINLOG $MYSQLD_DATADIR/$binlog_file > $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
|
||||
|
||||
--let SEARCH_PATTERN= GTID $analyze_gtid ddl
|
||||
--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
--let SEARCH_PATTERN= GTID $optimize_gtid ddl
|
||||
--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
--let SEARCH_PATTERN= GTID $repair_gtid ddl
|
||||
--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
--echo #
|
||||
--echo # Clean up
|
||||
--echo #
|
||||
DROP TABLE t1;
|
||||
--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out
|
||||
--save_master_pos
|
||||
|
||||
--connection server_2
|
||||
--sync_with_master
|
||||
|
||||
--source include/stop_slave.inc
|
||||
SET GLOBAL slave_parallel_threads= @save_slave_parallel_threads;
|
||||
SET GLOBAL slave_parallel_mode= @save_slave_parallel_mode;
|
||||
--source include/start_slave.inc
|
||||
|
||||
--source include/rpl_end.inc
|
19
mysql-test/suite/rpl/t/rpl_slave_shutdown_mdev20821.cnf
Normal file
19
mysql-test/suite/rpl/t/rpl_slave_shutdown_mdev20821.cnf
Normal file
@ -0,0 +1,19 @@
|
||||
!include suite/rpl/rpl_1slave_base.cnf
|
||||
!include include/default_client.cnf
|
||||
|
||||
[mysqld.1]
|
||||
log-slave-updates
|
||||
gtid-domain-id=1
|
||||
|
||||
[mysqld.2]
|
||||
log-slave-updates
|
||||
gtid-domain-id=2
|
||||
|
||||
[mysqld.3]
|
||||
log-slave-updates
|
||||
gtid-domain-id=3
|
||||
slave_parallel_threads=2
|
||||
|
||||
[ENV]
|
||||
SERVER_MYPORT_3= @mysqld.3.port
|
||||
SERVER_MYSOCK_3= @mysqld.3.socket
|
171
mysql-test/suite/rpl/t/rpl_slave_shutdown_mdev20821.test
Normal file
171
mysql-test/suite/rpl/t/rpl_slave_shutdown_mdev20821.test
Normal file
@ -0,0 +1,171 @@
|
||||
# MDEV-20821 parallel slave server shutdown hang
|
||||
#
|
||||
# Test the bug condition of a parallel slave server shutdown
|
||||
# hang when the parallel workers were idle.
|
||||
# The bug reported scenario is extented to cover the multi-sources case as well as
|
||||
# checking is done for both the idle and busy workers cases.
|
||||
#
|
||||
# MDEV-25336 Parallel replication causes failed assert while restarting
|
||||
# Since this test case involves slave restart this will help in testing
|
||||
# Mdev-25336 too.
|
||||
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_binlog_format_mixed.inc
|
||||
--let $rpl_topology= 1->3
|
||||
--source include/rpl_init.inc
|
||||
|
||||
#
|
||||
# A. idle workers.
|
||||
#
|
||||
--connection server_3
|
||||
set default_master_connection = '';
|
||||
--source include/start_slave.inc
|
||||
|
||||
set default_master_connection = 'm2';
|
||||
--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2
|
||||
eval change master to master_host='127.0.0.1', master_port=$SERVER_MYPORT_2, master_user='root', master_use_gtid=slave_pos;
|
||||
--source include/start_slave.inc
|
||||
|
||||
select @@global.slave_parallel_workers as two;
|
||||
|
||||
# At this point worker threads have no assignement.
|
||||
# Shutdown must not hang.
|
||||
# In 10.2/10.3 there should not be any assert failure `prev != 0 && next != 0'
|
||||
--connection server_3
|
||||
--write_file $MYSQLTEST_VARDIR/tmp/mysqld.3.expect
|
||||
wait
|
||||
EOF
|
||||
--send SHUTDOWN
|
||||
--reap
|
||||
--source include/wait_until_disconnected.inc
|
||||
|
||||
--connection server_3
|
||||
--append_file $MYSQLTEST_VARDIR/tmp/mysqld.3.expect
|
||||
restart
|
||||
EOF
|
||||
|
||||
# No hang is *proved* to occur when this point is reached.
|
||||
--connection server_3
|
||||
--enable_reconnect
|
||||
--source include/wait_until_connected_again.inc
|
||||
|
||||
#
|
||||
# B. resting workers after some busy time
|
||||
#
|
||||
--connection server_1
|
||||
create table t1 (i int primary key) engine=Innodb;
|
||||
|
||||
--connection server_2
|
||||
create table t2 (i int primary key) engine=Innodb;
|
||||
|
||||
--connection server_3
|
||||
set default_master_connection = '';
|
||||
--source include/start_slave.inc
|
||||
|
||||
set default_master_connection = 'm2';
|
||||
--source include/start_slave.inc
|
||||
|
||||
--connection server_2
|
||||
insert into t2 values (1);
|
||||
--save_master_pos
|
||||
|
||||
--connection server_3
|
||||
--sync_with_master 0,'m2'
|
||||
|
||||
--connection server_1
|
||||
insert into t1 values (1);
|
||||
--save_master_pos
|
||||
|
||||
--connection server_3
|
||||
--sync_with_master 0,''
|
||||
|
||||
# In 10.2/10.3 there should not be any assert failure `prev != 0 && next != 0'
|
||||
# At this point worker threads have no assignement.
|
||||
# Shutdown must not hang.
|
||||
|
||||
--connection server_3
|
||||
--write_file $MYSQLTEST_VARDIR/tmp/mysqld.3.expect
|
||||
wait
|
||||
EOF
|
||||
--send SHUTDOWN
|
||||
--reap
|
||||
--source include/wait_until_disconnected.inc
|
||||
|
||||
--connection server_3
|
||||
--append_file $MYSQLTEST_VARDIR/tmp/mysqld.3.expect
|
||||
restart
|
||||
EOF
|
||||
|
||||
# No hang is *proved* to occur when this point is reached.
|
||||
--connection server_3
|
||||
--enable_reconnect
|
||||
--source include/wait_until_connected_again.inc
|
||||
|
||||
#
|
||||
# C. busy workers
|
||||
#
|
||||
--connection server_3
|
||||
set default_master_connection = '';
|
||||
--source include/start_slave.inc
|
||||
|
||||
set default_master_connection = 'm2';
|
||||
--source include/start_slave.inc
|
||||
|
||||
--connect (conn_block_server3, 127.0.0.1, root,, test, $SERVER_MYPORT_3,)
|
||||
begin;
|
||||
insert into t1 values (2);
|
||||
insert into t2 values (2);
|
||||
|
||||
--connection server_1
|
||||
insert into t1 values (2);
|
||||
--connection server_2
|
||||
insert into t2 values (2);
|
||||
|
||||
|
||||
# In 10.2/10.3 there should not be any assert failure `prev != 0 && next != 0'
|
||||
# At this point there's a good chance the worker threads are busy.
|
||||
# SHUTDOWN must proceed without any delay as above.
|
||||
--connection server_3
|
||||
--write_file $MYSQLTEST_VARDIR/tmp/mysqld.3.expect
|
||||
wait
|
||||
EOF
|
||||
--send SHUTDOWN
|
||||
--reap
|
||||
--source include/wait_until_disconnected.inc
|
||||
|
||||
--connection server_3
|
||||
--append_file $MYSQLTEST_VARDIR/tmp/mysqld.3.expect
|
||||
restart
|
||||
EOF
|
||||
|
||||
# No hang is *proved* to occur when this point is reached.
|
||||
--connection server_3
|
||||
--enable_reconnect
|
||||
--source include/wait_until_connected_again.inc
|
||||
|
||||
|
||||
# Cleanup
|
||||
|
||||
--connection server_3
|
||||
set default_master_connection = '';
|
||||
--source include/start_slave.inc
|
||||
|
||||
set default_master_connection = 'm2';
|
||||
--source include/start_slave.inc
|
||||
|
||||
--connection server_1
|
||||
drop table t1;
|
||||
|
||||
--connection server_2
|
||||
drop table t2;
|
||||
--save_master_pos
|
||||
|
||||
# (!) The following block is critical to avoid check-mysqld_3.reject by mtr:
|
||||
--connection server_3
|
||||
--sync_with_master 0,'m2'
|
||||
set default_master_connection = 'm2';
|
||||
--source include/stop_slave.inc
|
||||
RESET SLAVE ALL;
|
||||
set default_master_connection = '';
|
||||
|
||||
--source include/rpl_end.inc
|
@ -1733,9 +1733,19 @@ struct THD_TRANS
|
||||
CREATED_TEMP_TABLE= 2,
|
||||
DROPPED_TEMP_TABLE= 4,
|
||||
DID_WAIT= 8,
|
||||
DID_DDL= 0x10
|
||||
DID_DDL= 0x10,
|
||||
EXECUTED_TABLE_ADMIN_CMD= 0x20
|
||||
};
|
||||
|
||||
void mark_executed_table_admin_cmd()
|
||||
{
|
||||
DBUG_PRINT("debug", ("mark_executed_table_admin_cmd"));
|
||||
m_unsafe_rollback_flags|= EXECUTED_TABLE_ADMIN_CMD;
|
||||
}
|
||||
bool trans_executed_admin_cmd()
|
||||
{
|
||||
return (m_unsafe_rollback_flags & EXECUTED_TABLE_ADMIN_CMD) != 0;
|
||||
}
|
||||
void mark_created_temp_table()
|
||||
{
|
||||
DBUG_PRINT("debug", ("mark_created_temp_table"));
|
||||
|
@ -7948,8 +7948,10 @@ Gtid_log_event::Gtid_log_event(THD *thd_arg, uint64 seq_no_arg,
|
||||
flags2|= FL_WAITED;
|
||||
if (thd_arg->transaction.stmt.trans_did_ddl() ||
|
||||
thd_arg->transaction.stmt.has_created_dropped_temp_table() ||
|
||||
thd_arg->transaction.stmt.trans_executed_admin_cmd() ||
|
||||
thd_arg->transaction.all.trans_did_ddl() ||
|
||||
thd_arg->transaction.all.has_created_dropped_temp_table())
|
||||
thd_arg->transaction.all.has_created_dropped_temp_table() ||
|
||||
thd_arg->transaction.all.trans_executed_admin_cmd())
|
||||
flags2|= FL_DDL;
|
||||
else if (is_transactional && !is_tmp_table)
|
||||
flags2|= FL_TRANSACTIONAL;
|
||||
|
@ -454,6 +454,7 @@ pool_mark_busy(rpl_parallel_thread_pool *pool, THD *thd)
|
||||
So we protect the infrequent operations of FLUSH TABLES WITH READ LOCK and
|
||||
pool size changes with this condition wait.
|
||||
*/
|
||||
DBUG_EXECUTE_IF("mark_busy_mdev_22370",my_sleep(1000000););
|
||||
mysql_mutex_lock(&pool->LOCK_rpl_thread_pool);
|
||||
if (thd)
|
||||
{
|
||||
@ -1999,10 +2000,24 @@ rpl_parallel_thread_pool::init(uint32 size)
|
||||
|
||||
void
|
||||
rpl_parallel_thread_pool::destroy()
|
||||
{
|
||||
deactivate();
|
||||
destroy_cond_mutex();
|
||||
}
|
||||
|
||||
void
|
||||
rpl_parallel_thread_pool::deactivate()
|
||||
{
|
||||
if (!inited)
|
||||
return;
|
||||
rpl_parallel_change_thread_count(this, 0, 1);
|
||||
}
|
||||
|
||||
void
|
||||
rpl_parallel_thread_pool::destroy_cond_mutex()
|
||||
{
|
||||
if (!inited)
|
||||
return;
|
||||
mysql_mutex_destroy(&LOCK_rpl_thread_pool);
|
||||
mysql_cond_destroy(&COND_rpl_thread_pool);
|
||||
inited= false;
|
||||
|
@ -244,6 +244,8 @@ struct rpl_parallel_thread_pool {
|
||||
rpl_parallel_thread_pool();
|
||||
int init(uint32 size);
|
||||
void destroy();
|
||||
void deactivate();
|
||||
void destroy_cond_mutex();
|
||||
struct rpl_parallel_thread *get_thread(rpl_parallel_thread **owner,
|
||||
rpl_parallel_entry *entry);
|
||||
void release_thread(rpl_parallel_thread *rpt);
|
||||
|
@ -207,8 +207,8 @@ a file name for --relay-log-index option", opt_relaylog_index_name);
|
||||
*/
|
||||
sql_print_warning("Neither --relay-log nor --relay-log-index were used;"
|
||||
" so replication "
|
||||
"may break when this MySQL server acts as a "
|
||||
"slave and has his hostname changed!! Please "
|
||||
"may break when this MariaDB server acts as a "
|
||||
"replica and has its hostname changed. Please "
|
||||
"use '--log-basename=#' or '--relay-log=%s' to avoid "
|
||||
"this problem.", ln);
|
||||
name_warning_sent= 1;
|
||||
|
@ -1261,6 +1261,9 @@ void slave_prepare_for_shutdown()
|
||||
mysql_mutex_lock(&LOCK_active_mi);
|
||||
master_info_index->free_connections();
|
||||
mysql_mutex_unlock(&LOCK_active_mi);
|
||||
// It's safe to destruct worker pool now when
|
||||
// all driver threads are gone.
|
||||
global_rpl_thread_pool.deactivate();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Copyright (c) 2010, 2015, Oracle and/or its affiliates.
|
||||
Copyright (c) 2011, 2020, MariaDB
|
||||
Copyright (c) 2011, 2021, MariaDB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -455,7 +455,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
|
||||
int (handler::*operator_func)(THD *,
|
||||
HA_CHECK_OPT *),
|
||||
int (view_operator_func)(THD *, TABLE_LIST*,
|
||||
HA_CHECK_OPT *))
|
||||
HA_CHECK_OPT *),
|
||||
bool is_cmd_replicated)
|
||||
{
|
||||
TABLE_LIST *table;
|
||||
List<Item> field_list;
|
||||
@ -466,6 +467,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
|
||||
int compl_result_code;
|
||||
bool need_repair_or_alter= 0;
|
||||
wait_for_commit* suspended_wfc;
|
||||
bool is_table_modified= false;
|
||||
|
||||
DBUG_ENTER("mysql_admin_table");
|
||||
DBUG_PRINT("enter", ("extra_open_options: %u", extra_open_options));
|
||||
|
||||
@ -515,6 +518,10 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
|
||||
bool open_for_modify= org_open_for_modify;
|
||||
|
||||
DBUG_PRINT("admin", ("table: '%s'.'%s'", db, table->table_name.str));
|
||||
DEBUG_SYNC(thd, "admin_command_kill_before_modify");
|
||||
|
||||
if (thd->is_killed())
|
||||
break;
|
||||
strxmov(table_name, db, ".", table->table_name.str, NullS);
|
||||
thd->open_options|= extra_open_options;
|
||||
table->lock_type= lock_type;
|
||||
@ -1167,6 +1174,13 @@ send_result_message:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
Admin commands acquire table locks and these locks are not detected by
|
||||
parallel replication deadlock detection-and-handling mechanism. Hence
|
||||
they must be marked as DDL so that they are not scheduled in parallel
|
||||
with conflicting DMLs resulting in deadlock.
|
||||
*/
|
||||
thd->transaction.stmt.mark_executed_table_admin_cmd();
|
||||
if (table->table && !table->view)
|
||||
{
|
||||
if (table->table->s->tmp_table)
|
||||
@ -1202,10 +1216,9 @@ send_result_message:
|
||||
}
|
||||
else
|
||||
{
|
||||
if (trans_commit_stmt(thd) ||
|
||||
(stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_END) &&
|
||||
trans_commit_implicit(thd)))
|
||||
if (trans_commit_stmt(thd))
|
||||
goto err;
|
||||
is_table_modified= true;
|
||||
}
|
||||
close_thread_tables(thd);
|
||||
thd->release_transactional_locks();
|
||||
@ -1228,6 +1241,13 @@ send_result_message:
|
||||
|
||||
if (protocol->write())
|
||||
goto err;
|
||||
DEBUG_SYNC(thd, "admin_command_kill_after_modify");
|
||||
}
|
||||
if (is_table_modified && is_cmd_replicated &&
|
||||
(!opt_readonly || thd->slave_thread) && !thd->lex->no_write_to_binlog)
|
||||
{
|
||||
if (write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
|
||||
goto err;
|
||||
}
|
||||
|
||||
my_eof(thd);
|
||||
@ -1290,7 +1310,7 @@ bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
|
||||
check_opt.key_cache= key_cache;
|
||||
DBUG_RETURN(mysql_admin_table(thd, tables, &check_opt,
|
||||
"assign_to_keycache", TL_READ_NO_INSERT, 0, 0,
|
||||
0, 0, &handler::assign_to_keycache, 0));
|
||||
0, 0, &handler::assign_to_keycache, 0, false));
|
||||
}
|
||||
|
||||
|
||||
@ -1317,7 +1337,7 @@ bool mysql_preload_keys(THD* thd, TABLE_LIST* tables)
|
||||
*/
|
||||
DBUG_RETURN(mysql_admin_table(thd, tables, 0,
|
||||
"preload_keys", TL_READ_NO_INSERT, 0, 0, 0, 0,
|
||||
&handler::preload_keys, 0));
|
||||
&handler::preload_keys, 0, false));
|
||||
}
|
||||
|
||||
|
||||
@ -1335,15 +1355,7 @@ bool Sql_cmd_analyze_table::execute(THD *thd)
|
||||
WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, first_table);
|
||||
res= mysql_admin_table(thd, first_table, &m_lex->check_opt,
|
||||
"analyze", lock_type, 1, 0, 0, 0,
|
||||
&handler::ha_analyze, 0);
|
||||
/* ! we write after unlocking the table */
|
||||
if (!res && !m_lex->no_write_to_binlog && (!opt_readonly || thd->slave_thread))
|
||||
{
|
||||
/*
|
||||
Presumably, ANALYZE and binlog writing doesn't require synchronization
|
||||
*/
|
||||
res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
|
||||
}
|
||||
&handler::ha_analyze, 0, true);
|
||||
m_lex->select_lex.table_list.first= first_table;
|
||||
m_lex->query_tables= first_table;
|
||||
|
||||
@ -1367,7 +1379,7 @@ bool Sql_cmd_check_table::execute(THD *thd)
|
||||
|
||||
res= mysql_admin_table(thd, first_table, &m_lex->check_opt, "check",
|
||||
lock_type, 0, 0, HA_OPEN_FOR_REPAIR, 0,
|
||||
&handler::ha_check, &view_check);
|
||||
&handler::ha_check, &view_check, false);
|
||||
|
||||
m_lex->select_lex.table_list.first= first_table;
|
||||
m_lex->query_tables= first_table;
|
||||
@ -1393,15 +1405,7 @@ bool Sql_cmd_optimize_table::execute(THD *thd)
|
||||
mysql_recreate_table(thd, first_table, true) :
|
||||
mysql_admin_table(thd, first_table, &m_lex->check_opt,
|
||||
"optimize", TL_WRITE, 1, 0, 0, 0,
|
||||
&handler::ha_optimize, 0);
|
||||
/* ! we write after unlocking the table */
|
||||
if (!res && !m_lex->no_write_to_binlog && (!opt_readonly || thd->slave_thread))
|
||||
{
|
||||
/*
|
||||
Presumably, OPTIMIZE and binlog writing doesn't require synchronization
|
||||
*/
|
||||
res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
|
||||
}
|
||||
&handler::ha_optimize, 0, true);
|
||||
m_lex->select_lex.table_list.first= first_table;
|
||||
m_lex->query_tables= first_table;
|
||||
|
||||
@ -1426,16 +1430,8 @@ bool Sql_cmd_repair_table::execute(THD *thd)
|
||||
TL_WRITE, 1,
|
||||
MY_TEST(m_lex->check_opt.sql_flags & TT_USEFRM),
|
||||
HA_OPEN_FOR_REPAIR, &prepare_for_repair,
|
||||
&handler::ha_repair, &view_repair);
|
||||
&handler::ha_repair, &view_repair, true);
|
||||
|
||||
/* ! we write after unlocking the table */
|
||||
if (!res && !m_lex->no_write_to_binlog && (!opt_readonly || thd->slave_thread))
|
||||
{
|
||||
/*
|
||||
Presumably, REPAIR and binlog writing doesn't require synchronization
|
||||
*/
|
||||
res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
|
||||
}
|
||||
m_lex->select_lex.table_list.first= first_table;
|
||||
m_lex->query_tables= first_table;
|
||||
|
||||
|
@ -4823,7 +4823,8 @@ public:
|
||||
transaction.all.m_unsafe_rollback_flags|=
|
||||
(transaction.stmt.m_unsafe_rollback_flags &
|
||||
(THD_TRANS::DID_WAIT | THD_TRANS::CREATED_TEMP_TABLE |
|
||||
THD_TRANS::DROPPED_TEMP_TABLE | THD_TRANS::DID_DDL));
|
||||
THD_TRANS::DROPPED_TEMP_TABLE | THD_TRANS::DID_DDL |
|
||||
THD_TRANS::EXECUTED_TABLE_ADMIN_CMD));
|
||||
}
|
||||
/*
|
||||
Reset current_linfo
|
||||
|
@ -9312,8 +9312,12 @@ ha_innobase::index_read(
|
||||
|
||||
/* For R-Tree index, we will always place the page lock to
|
||||
pages being searched */
|
||||
if (dict_index_is_spatial(index)) {
|
||||
++m_prebuilt->trx->will_lock;
|
||||
if (index->is_spatial() && !m_prebuilt->trx->will_lock) {
|
||||
if (trx_is_started(m_prebuilt->trx)) {
|
||||
DBUG_RETURN(HA_ERR_READ_ONLY_TRANSACTION);
|
||||
} else {
|
||||
m_prebuilt->trx->will_lock = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Note that if the index for which the search template is built is not
|
||||
|
Loading…
x
Reference in New Issue
Block a user