Bug #73903 Optimize the log_lock mutex for mysql_binlog_send call
Submitted: 12 Sep 2014 8:34 Modified: 30 Oct 2014 23:55
Reporter: Fangxin Flou (OCA) Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Cluster: Replication Severity:S5 (Performance)
Version:All OS:Any
Assigned to: CPU Architecture:Any
Tags: binlog

[12 Sep 2014 8:34] Fangxin Flou
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
[14 Sep 2014 15:08] zhai weixiang
LOCK_log is removed completely from dump thread in MySQL 5.7
[30 Oct 2014 23:55] Fangxin Flou
LOCK_log is removed completely from dump thread in MySQL 5.7