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.000004 #
|
||||||
master-bin.000005 #
|
master-bin.000005 #
|
||||||
master-bin.000006 #
|
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;
|
DROP TABLE t1, t2;
|
||||||
SET GLOBAL max_binlog_size= @old_max_binlog_size;
|
SET GLOBAL max_binlog_size= @old_max_binlog_size;
|
||||||
SET GLOBAL innodb_flush_log_at_trx_commit= @old_innodb_flush_log_at_trx_commit;
|
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;
|
SET GLOBAL debug_dbug= @old_dbug;
|
||||||
INSERT INTO t1 VALUES (31, REPEAT("x", 4100));
|
INSERT INTO t1 VALUES (31, REPEAT("x", 4100));
|
||||||
--source include/show_binary_logs.inc
|
--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;
|
DROP TABLE t1, t2;
|
||||||
SET GLOBAL max_binlog_size= @old_max_binlog_size;
|
SET GLOBAL max_binlog_size= @old_max_binlog_size;
|
||||||
SET GLOBAL innodb_flush_log_at_trx_commit= @old_innodb_flush_log_at_trx_commit;
|
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)
|
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),
|
bytes_written(0), file_id(1), open_count(1),
|
||||||
group_commit_queue(0), group_commit_queue_busy(FALSE),
|
group_commit_queue(0), group_commit_queue_busy(FALSE),
|
||||||
num_commits(0), num_group_commits(0),
|
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.
|
do this before we take the LOCK_log to not deadlock.
|
||||||
*/
|
*/
|
||||||
mysql_mutex_lock(&LOCK_xid_list);
|
mysql_mutex_lock(&LOCK_xid_list);
|
||||||
reset_master_pending= true;
|
reset_master_pending++;
|
||||||
while (mark_xid_done_waiting > 0)
|
while (mark_xid_done_waiting > 0)
|
||||||
mysql_cond_wait(&COND_xid_list, &LOCK_xid_list);
|
mysql_cond_wait(&COND_xid_list, &LOCK_xid_list);
|
||||||
mysql_mutex_unlock(&LOCK_xid_list);
|
mysql_mutex_unlock(&LOCK_xid_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG_SYNC(thd, "reset_logs_after_set_reset_master_pending");
|
||||||
if (thd)
|
if (thd)
|
||||||
ha_reset_logs(thd);
|
ha_reset_logs(thd);
|
||||||
/*
|
/*
|
||||||
@@ -4054,7 +4055,7 @@ err:
|
|||||||
DBUG_ASSERT(b->xid_count == 0);
|
DBUG_ASSERT(b->xid_count == 0);
|
||||||
my_free(binlog_xid_count_list.get());
|
my_free(binlog_xid_count_list.get());
|
||||||
}
|
}
|
||||||
reset_master_pending= false;
|
reset_master_pending--;
|
||||||
mysql_mutex_unlock(&LOCK_xid_list);
|
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
|
anyway). Instead we should signal COND_xid_list whenever a new binlog
|
||||||
checkpoint arrives - when all have arrived, RESET MASTER will complete.
|
checkpoint arrives - when all have arrived, RESET MASTER will complete.
|
||||||
*/
|
*/
|
||||||
bool reset_master_pending;
|
uint reset_master_pending;
|
||||||
ulong mark_xid_done_waiting;
|
ulong mark_xid_done_waiting;
|
||||||
|
|
||||||
/* LOCK_log and LOCK_index are inited by init_pthread_objects() */
|
/* LOCK_log and LOCK_index are inited by init_pthread_objects() */
|
||||||
|
Reference in New Issue
Block a user