Bug #73903 Optimize the log_lock mutex for mysql_binlog_send call
Description:
I found that in mysql_binlog_send, every call to Log_event::read_log_event is protected by the global LOCK_log mutex, even we are dumping the old binlog file, this is not reasonable, it makes the TPS not so stable.
So I suggest to optimize this mutex lock, if we are not reading the current binlog file, log_lock is not required, if we are reading the flushed part of the file, log_lock is not required.
How to repeat:
N/A
Suggested fix:
in binlog.cc
/**
Call fsync() to sync the file to disk.
*/
std::pair<bool, bool>
MYSQL_BIN_LOG::sync_binlog_file(bool force)
{
bool synced= false;
unsigned int sync_period= get_sync_period();
if (srv_flush_log_at_trx_commit == 3) sync_period = 0;
if (force || (sync_period && ++sync_counter >= sync_period))
{
sync_counter= 0;
if (mysql_file_sync(log_file.file, MYF(MY_WME)))
return std::make_pair(true, synced);
if (is_relay_log == 0)
{
// remember the log file index & log file length
......
}
synced= true;
}
return std::make_pair(false, synced);
}
in rpl_master.cc
if (pos > BIN_LOG_HEADER_SIZE)
{
/* reset transmit packet for the event read from binary log
file */
if (reset_transmit_packet(thd, flags, &ev_offset, &errmsg,
observe_transmission))
GOTO_ERR;
/*
Try to find a Format_description_log_event at the beginning of
the binlog
*/
if (!(error = Log_event::read_log_event(&log, packet, (is behind the last position ? NULL : log_lock), 0)))
{
DBUG_PRINT("info", ("read_log_event returned 0 on line %d", __LINE__));
/*
The packet has offsets equal to the normal offsets in a
binlog event + ev_offset (the first ev_offset characters are
the header (default \0)).
*/
while (!net->error && net->vio != 0 && !thd->killed)
{
Log_event_type event_type= UNKNOWN_EVENT;
bool goto_next_binlog= false;
/* reset the transmit packet for the event read from binary log
file */
if (reset_transmit_packet(thd, flags, &ev_offset, &errmsg,
observe_transmission))
GOTO_ERR;
DBUG_EXECUTE_IF("semi_sync_3-way_deadlock",
{
const char act[]= "now wait_for signal.rotate_finished no_clear_event";
DBUG_ASSERT(!debug_sync_set_action(current_thd,
STRING_WITH_LEN(act)));
};);
bool is_active_binlog= false;
while (!(error= Log_event::read_log_event(&log, packet, (is behind the last position ? NULL : log_lock),
current_checksum_alg,
log_file_name,
&is_active_binlog)))
{
DBUG_PRINT("info", ("read_log_event returned 0 on line %d", __LINE__));
#ifndef DBUG_OFF
if (max_binlog_dump_events && !left_events--)
{
net_flush(net);
errmsg = "Debugging binlog dump abort";
my_errno= ER_UNKNOWN_ERROR;
GOTO_ERR;
}
#endif
Portions of this website are copyright © 2001, 2002 The PHP Group
Page generated in 0.040 sec. using MySQL 8.4.7-u6-cloud
Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the
respective copyright holders.
It is not reviewed in advance
by Oracle and does not necessarily represent the opinion of
Oracle or any other party.
Description: I found that in mysql_binlog_send, every call to Log_event::read_log_event is protected by the global LOCK_log mutex, even we are dumping the old binlog file, this is not reasonable, it makes the TPS not so stable. So I suggest to optimize this mutex lock, if we are not reading the current binlog file, log_lock is not required, if we are reading the flushed part of the file, log_lock is not required. How to repeat: N/A Suggested fix: in binlog.cc /** Call fsync() to sync the file to disk. */ std::pair<bool, bool> MYSQL_BIN_LOG::sync_binlog_file(bool force) { bool synced= false; unsigned int sync_period= get_sync_period(); if (srv_flush_log_at_trx_commit == 3) sync_period = 0; if (force || (sync_period && ++sync_counter >= sync_period)) { sync_counter= 0; if (mysql_file_sync(log_file.file, MYF(MY_WME))) return std::make_pair(true, synced); if (is_relay_log == 0) { // remember the log file index & log file length ...... } synced= true; } return std::make_pair(false, synced); } in rpl_master.cc if (pos > BIN_LOG_HEADER_SIZE) { /* reset transmit packet for the event read from binary log file */ if (reset_transmit_packet(thd, flags, &ev_offset, &errmsg, observe_transmission)) GOTO_ERR; /* Try to find a Format_description_log_event at the beginning of the binlog */ if (!(error = Log_event::read_log_event(&log, packet, (is behind the last position ? NULL : log_lock), 0))) { DBUG_PRINT("info", ("read_log_event returned 0 on line %d", __LINE__)); /* The packet has offsets equal to the normal offsets in a binlog event + ev_offset (the first ev_offset characters are the header (default \0)). */ while (!net->error && net->vio != 0 && !thd->killed) { Log_event_type event_type= UNKNOWN_EVENT; bool goto_next_binlog= false; /* reset the transmit packet for the event read from binary log file */ if (reset_transmit_packet(thd, flags, &ev_offset, &errmsg, observe_transmission)) GOTO_ERR; DBUG_EXECUTE_IF("semi_sync_3-way_deadlock", { const char act[]= "now wait_for signal.rotate_finished no_clear_event"; DBUG_ASSERT(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act))); };); bool is_active_binlog= false; while (!(error= Log_event::read_log_event(&log, packet, (is behind the last position ? NULL : log_lock), current_checksum_alg, log_file_name, &is_active_binlog))) { DBUG_PRINT("info", ("read_log_event returned 0 on line %d", __LINE__)); #ifndef DBUG_OFF if (max_binlog_dump_events && !left_events--) { net_flush(net); errmsg = "Debugging binlog dump abort"; my_errno= ER_UNKNOWN_ERROR; GOTO_ERR; } #endif