mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-7402 'reset master' hangs, waits for signalled COND_xid_list
Using a boolean flag for 'there is a RESET MASTER in progress' doesn't work very well for multiple concurrent RESET MASTER statements. Changed to a counter.
This commit is contained in:
@@ -112,6 +112,18 @@ master-bin.000003 #
|
||||
master-bin.000004 #
|
||||
master-bin.000005 #
|
||||
master-bin.000006 #
|
||||
SET debug_sync = 'reset';
|
||||
*** MDEV-7402: 'reset master' hangs, waits for signalled COND_xid_list ***
|
||||
SET debug_sync="reset_logs_after_set_reset_master_pending SIGNAL reset_master_ready WAIT_FOR reset_master_cont";
|
||||
RESET MASTER;
|
||||
SET @old_dbug= @@global.DEBUG_DBUG;
|
||||
SET GLOBAL debug_dbug="+d,inject_binlog_background_thread_before_mark_xid_done";
|
||||
SET debug_sync="now WAIT_FOR reset_master_ready";
|
||||
RESET MASTER;
|
||||
SET debug_sync="now WAIT_FOR injected_binlog_background_thread";
|
||||
SET GLOBAL debug_dbug=@old_dbug;
|
||||
SET debug_sync="now SIGNAL reset_master_cont";
|
||||
SET debug_sync = 'reset';
|
||||
DROP TABLE t1, t2;
|
||||
SET GLOBAL max_binlog_size= @old_max_binlog_size;
|
||||
SET GLOBAL innodb_flush_log_at_trx_commit= @old_innodb_flush_log_at_trx_commit;
|
||||
|
@@ -138,8 +138,39 @@ SET DEBUG_SYNC= "now WAIT_FOR injected_binlog_background_thread";
|
||||
SET GLOBAL debug_dbug= @old_dbug;
|
||||
INSERT INTO t1 VALUES (31, REPEAT("x", 4100));
|
||||
--source include/show_binary_logs.inc
|
||||
SET debug_sync = 'reset';
|
||||
|
||||
|
||||
--echo *** MDEV-7402: 'reset master' hangs, waits for signalled COND_xid_list ***
|
||||
|
||||
--source include/wait_for_binlog_checkpoint.inc
|
||||
|
||||
connect(con3,localhost,root,,);
|
||||
# Make the binlog background thread wait before clearing the pending checkpoint.
|
||||
# The bug was that one RESET MASTER would clear the reset_master_pending
|
||||
# flag set by another RESET MASTER; this could cause the wakeup from the
|
||||
# binlog background thread not to be sent, and thus the second RESET MASTER
|
||||
# to wait infinitely.
|
||||
SET debug_sync="reset_logs_after_set_reset_master_pending SIGNAL reset_master_ready WAIT_FOR reset_master_cont";
|
||||
send RESET MASTER;
|
||||
|
||||
--connection default
|
||||
SET @old_dbug= @@global.DEBUG_DBUG;
|
||||
SET GLOBAL debug_dbug="+d,inject_binlog_background_thread_before_mark_xid_done";
|
||||
SET debug_sync="now WAIT_FOR reset_master_ready";
|
||||
RESET MASTER;
|
||||
SET debug_sync="now WAIT_FOR injected_binlog_background_thread";
|
||||
SET GLOBAL debug_dbug=@old_dbug;
|
||||
SET debug_sync="now SIGNAL reset_master_cont";
|
||||
|
||||
--connection con3
|
||||
REAP;
|
||||
|
||||
--connection default
|
||||
SET debug_sync = 'reset';
|
||||
|
||||
|
||||
# Clean up.
|
||||
DROP TABLE t1, t2;
|
||||
SET GLOBAL max_binlog_size= @old_max_binlog_size;
|
||||
SET GLOBAL innodb_flush_log_at_trx_commit= @old_innodb_flush_log_at_trx_commit;
|
||||
|
@@ -3031,7 +3031,7 @@ const char *MYSQL_LOG::generate_name(const char *log_name,
|
||||
|
||||
|
||||
MYSQL_BIN_LOG::MYSQL_BIN_LOG(uint *sync_period)
|
||||
:reset_master_pending(false), mark_xid_done_waiting(0),
|
||||
:reset_master_pending(0), mark_xid_done_waiting(0),
|
||||
bytes_written(0), file_id(1), open_count(1),
|
||||
group_commit_queue(0), group_commit_queue_busy(FALSE),
|
||||
num_commits(0), num_group_commits(0),
|
||||
@@ -3867,12 +3867,13 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd, bool create_new_log,
|
||||
do this before we take the LOCK_log to not deadlock.
|
||||
*/
|
||||
mysql_mutex_lock(&LOCK_xid_list);
|
||||
reset_master_pending= true;
|
||||
reset_master_pending++;
|
||||
while (mark_xid_done_waiting > 0)
|
||||
mysql_cond_wait(&COND_xid_list, &LOCK_xid_list);
|
||||
mysql_mutex_unlock(&LOCK_xid_list);
|
||||
}
|
||||
|
||||
DEBUG_SYNC(thd, "reset_logs_after_set_reset_master_pending");
|
||||
if (thd)
|
||||
ha_reset_logs(thd);
|
||||
/*
|
||||
@@ -4054,7 +4055,7 @@ err:
|
||||
DBUG_ASSERT(b->xid_count == 0);
|
||||
my_free(binlog_xid_count_list.get());
|
||||
}
|
||||
reset_master_pending= false;
|
||||
reset_master_pending--;
|
||||
mysql_mutex_unlock(&LOCK_xid_list);
|
||||
}
|
||||
|
||||
|
@@ -470,7 +470,7 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
|
||||
anyway). Instead we should signal COND_xid_list whenever a new binlog
|
||||
checkpoint arrives - when all have arrived, RESET MASTER will complete.
|
||||
*/
|
||||
bool reset_master_pending;
|
||||
uint reset_master_pending;
|
||||
ulong mark_xid_done_waiting;
|
||||
|
||||
/* LOCK_log and LOCK_index are inited by init_pthread_objects() */
|
||||
|
Reference in New Issue
Block a user