Merge 10.2 into 10.3, except MDEV-25682

This commit is contained in:
Marko Mäkelä 2021-05-18 08:40:19 +03:00
commit ca3f497564
21 changed files with 722 additions and 45 deletions

View File

@ -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;

View File

@ -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]) }

View File

@ -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;

View File

@ -0,0 +1,4 @@
connect con1,localhost,root,,;
SET DEBUG_DBUG='+d,mark_busy_mdev_22370';
FLUSH TABLES WITH READ LOCK;
connection default;

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

@ -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"));

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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();
}
/*

View File

@ -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;

View File

@ -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

View File

@ -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