mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-450: Deadlock between starting a slave and reading system variables
Starting the SQL thread might deadlock with reading the values of the replication filtering options. The deadlock is due to a lock order violation when the variables are read or set. For example, reading replicate_ignore_table first acquires LOCK_global_system_variables in sys_var::value_ptr and later acquires LOCK_active_mi in Sys_var_rpl_filter::global_value_ptr. This violates the order established when starting a SQL thread, where LOCK_active_mi is acquired before start_slave, and ends up creating a thread (handle_slave_sql) that allocates a THD handle whose constructor acquires LOCK_global_system_variables in THD::init. The solution is to unlock LOCK_global_system_variables before the replication filtering options are set or read. This way the lock order is preserved and the data being read/set is still protected given that it acquires LOCK_active_mi.
This commit is contained in:
@ -0,0 +1,31 @@
|
||||
include/master-slave.inc
|
||||
[connection master]
|
||||
# connection: slave
|
||||
SET @save_slave_net_timeout = @@GLOBAL.slave_net_timeout;
|
||||
STOP SLAVE;
|
||||
include/wait_for_slave_to_stop.inc
|
||||
# open an extra connection to the slave
|
||||
# connection: slave2
|
||||
# set debug synchronization point
|
||||
SET DEBUG_SYNC='fix_slave_net_timeout SIGNAL parked WAIT_FOR go';
|
||||
# attempt to set slave_net_timeout, will wait on sync point
|
||||
SET @@GLOBAL.slave_net_timeout = 100;
|
||||
# connection: slave
|
||||
SET DEBUG_SYNC='now WAIT_FOR parked';
|
||||
# connection: slave1
|
||||
# attempt to start the SQL thread
|
||||
START SLAVE SQL_THREAD;
|
||||
# connection: slave
|
||||
# wait until SQL thread has been started
|
||||
# sleep a bit so that the SQL thread THD handle is initialized
|
||||
# signal the set slave_net_timeout to continue
|
||||
SET DEBUG_SYNC='now SIGNAL go';
|
||||
# connection: slave2
|
||||
# reap result of set slave_net_timeout
|
||||
# connection: slave1
|
||||
# reap result of starting the SQL thread
|
||||
# disconnect: slave2
|
||||
# connection: slave
|
||||
# cleanup
|
||||
SET @@GLOBAL.slave_net_timeout = @save_slave_net_timeout;
|
||||
include/rpl_end.inc
|
@ -0,0 +1,57 @@
|
||||
source include/master-slave.inc;
|
||||
source include/have_debug_sync.inc;
|
||||
|
||||
--echo # connection: slave
|
||||
connection slave;
|
||||
SET @save_slave_net_timeout = @@GLOBAL.slave_net_timeout;
|
||||
STOP SLAVE;
|
||||
source include/wait_for_slave_to_stop.inc;
|
||||
|
||||
--echo # open an extra connection to the slave
|
||||
connect(slave2,127.0.0.1,root,,test,$SLAVE_MYPORT,);
|
||||
--echo # connection: slave2
|
||||
--echo # set debug synchronization point
|
||||
SET DEBUG_SYNC='fix_slave_net_timeout SIGNAL parked WAIT_FOR go';
|
||||
--echo # attempt to set slave_net_timeout, will wait on sync point
|
||||
--send SET @@GLOBAL.slave_net_timeout = 100
|
||||
|
||||
--echo # connection: slave
|
||||
connection slave;
|
||||
SET DEBUG_SYNC='now WAIT_FOR parked';
|
||||
|
||||
--echo # connection: slave1
|
||||
connection slave1;
|
||||
--echo # attempt to start the SQL thread
|
||||
--send START SLAVE SQL_THREAD
|
||||
|
||||
--echo # connection: slave
|
||||
connection slave;
|
||||
--echo # wait until SQL thread has been started
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for slave thread to start" and info = "START SLAVE SQL_THREAD";
|
||||
--source include/wait_condition.inc
|
||||
--echo # sleep a bit so that the SQL thread THD handle is initialized
|
||||
sleep 2;
|
||||
--echo # signal the set slave_net_timeout to continue
|
||||
SET DEBUG_SYNC='now SIGNAL go';
|
||||
|
||||
--echo # connection: slave2
|
||||
connection slave2;
|
||||
--echo # reap result of set slave_net_timeout
|
||||
--reap
|
||||
|
||||
--echo # connection: slave1
|
||||
connection slave1;
|
||||
--echo # reap result of starting the SQL thread
|
||||
--reap
|
||||
|
||||
--echo # disconnect: slave2
|
||||
disconnect slave2;
|
||||
|
||||
--echo # connection: slave
|
||||
connection slave;
|
||||
--echo # cleanup
|
||||
SET @@GLOBAL.slave_net_timeout = @save_slave_net_timeout;
|
||||
|
||||
source include/rpl_end.inc;
|
Reference in New Issue
Block a user