mysql sync_binlog與組提交的關係

組提交參數:binlog_group_commit_sync_delay

Controls how many microseconds the binary log commit waits before synchronizing the binary log file to disk. By default binlog_group_commit_sync_delay is set to 0, meaning that there is no delay. S
binlog_group_commit_sync_no_delay_count
he maximum number of transactions to wait for before aborting the current delay as specified by binlog_group_commit_sync_delay

默認都是0

When sync_binlog=0 or sync_binlog=1 is set, the delay specified by binlog_group_commit_sync_delay is applied for every binary log commit group before synchronization (or in the case of sync_binlog=0, before proceeding). When sync_binlog is set to a value n greater than 1, the delay is applied after every n binary log commit groups.

看到sync_binlog是影響上面延時參數對多少組有影響。默認就是每一個組都會馬上進行刷binlog,沒有延時。

那麼在組提交的3個階段中,每個階段要處理多少組?每組有多少事務?有哪些參數控制?

看下5,7源碼,這部分函數是處理flush的函數,看到是fush了total_bytes_var 字節的數據,函數裏面有記錄一個組需要flush多少次。

/**
  Execute the flush stage.

  @param total_bytes_var Pointer to variable that will be set to total
  number of bytes flushed, or NULL.

  @param rotate_var Pointer to variable that will be set to true if
  binlog rotation should be performed after releasing locks. If rotate
  is not necessary, the variable will not be touched.

  @return Error code on error, zero on success
 */

int
MYSQL_BIN_LOG::process_flush_stage_queue(my_off_t *total_bytes_var,
                                         bool *rotate_var,
                                         THD **out_queue_var)
{
  DBUG_ENTER("MYSQL_BIN_LOG::process_flush_stage_queue");
  #ifndef DBUG_OFF
  // number of flushes per group.
  int no_flushes= 0;
  #endif
  DBUG_ASSERT(total_bytes_var && rotate_var && out_queue_var);
  my_off_t total_bytes= 0;
  int flush_error= 1;
  mysql_mutex_assert_owner(&LOCK_log);

  /*
    Fetch the entire flush queue and empty it, so that the next batch
    has a leader. We must do this before invoking ha_flush_logs(...)
    for guaranteeing to flush prepared records of transactions before
    flushing them to binary log, which is required by crash recovery.
  */
  THD *first_seen= stage_manager.fetch_queue_for(Stage_manager::FLUSH_STAGE);
  DBUG_ASSERT(first_seen != NULL);
  /*
    We flush prepared records of transactions to the log of storage
    engine (for example, InnoDB redo log) in a group right before
    flushing them to binary log.
  */
  ha_flush_logs(NULL, true);
  DBUG_EXECUTE_IF("crash_after_flush_engine_log", DBUG_SUICIDE(););
  assign_automatic_gtids_to_flush_group(first_seen);
  /* Flush thread caches to binary log. */
  for (THD *head= first_seen ; head ; head = head->next_to_commit)
  {
    std::pair<int,my_off_t> result= flush_thread_caches(head);
    total_bytes+= result.second;
    if (flush_error == 1)
      flush_error= result.first;
#ifndef DBUG_OFF
    no_flushes++; ---每個組中每個事務單獨刷一次到cache?
#endif
  }

  *out_queue_var= first_seen;
  *total_bytes_var= total_bytes;
  if (total_bytes > 0 && my_b_tell(&log_file) >= (my_off_t) max_size)
    *rotate_var= true;
#ifndef DBUG_OFF
  DBUG_PRINT("info",("no_flushes:= %d", no_flushes));
  no_flushes= 0;
#endif
  DBUG_RETURN(flush_error);
}
獲取隊列清空,這個函數中看到DBUG_PRINT("info", ("fetched queue of %d transactions", my_atomic_load32(&m_size)));
m_size就是事務的數量

THD *Stage_manager::Mutex_queue::fetch_and_empty()
{
  DBUG_ENTER("Stage_manager::Mutex_queue::fetch_and_empty");
  lock();
  DBUG_PRINT("enter", ("m_first: 0x%llx, &m_first: 0x%llx, m_last: 0x%llx",
                       (ulonglong) m_first, (ulonglong) &m_first,
                       (ulonglong) m_last));
  THD *result= m_first;
  m_first= NULL;
  m_last= &m_first;
  DBUG_PRINT("info", ("m_first: 0x%llx, &m_first: 0x%llx, m_last: 0x%llx",
                       (ulonglong) m_first, (ulonglong) &m_first,
                       (ulonglong) m_last));
  DBUG_PRINT("info", ("fetched queue of %d transactions", my_atomic_load32(&m_size)));
  DBUG_PRINT("return", ("result: 0x%llx", (ulonglong) result));
  DBUG_ASSERT(my_atomic_load32(&m_size) >= 0);
  my_atomic_store32(&m_size, 0);
  unlock();
  DBUG_RETURN(result);
}
在stage管理器上有m_size代表queue大小
/**
  Class for maintaining the commit stages for binary log group commit.
 */
class Stage_manager {
public:
  class Mutex_queue {
    friend class Stage_manager;
  public:
    Mutex_queue()
      : m_first(NULL), m_last(&m_first), m_size(0)
    {
    }

    void init(
#ifdef HAVE_PSI_INTERFACE
              PSI_mutex_key key_LOCK_queue
#endif
              ) {
      mysql_mutex_init(key_LOCK_queue, &m_lock, MY_MUTEX_INIT_FAST);
    }

    void deinit() {
      mysql_mutex_destroy(&m_lock);
    }

    bool is_empty() const {
      return m_first == NULL;
    }

    /**
      Append a linked list of threads to the queue.
      @retval true The queue was empty before this operation.
      @retval false The queue was non-empty before this operation.
    */
    bool append(THD *first);

    /**
       Fetch the entire queue for a stage.

       This will fetch the entire queue in one go.
    */
    THD *fetch_and_empty();

    std::pair<bool,THD*> pop_front();

    inline int32 get_size()
    {
      return my_atomic_load32(&m_size);
    }

  private:
    void lock() { mysql_mutex_lock(&m_lock); }
    void unlock() { mysql_mutex_unlock(&m_lock); }

    /**
       Pointer to the first thread in the queue, or NULL if the queue is
       empty.
    */
    THD *m_first;

    /**
       Pointer to the location holding the end of the queue.

       This is either @c &first, or a pointer to the @c next_to_commit of
       the last thread that is enqueued.
    */
    THD **m_last;

    /** size of the queue */
    int32 m_size;

    /** Lock for protecting the queue. */
    mysql_mutex_t m_lock;
    /*
      This attribute did not have the desired effect, at least not according
      to -fsanitize=undefined with gcc 5.2.1
      Also: it fails to compile with gcc 7.2
     */
  }; // MY_ATTRIBUTE((aligned(CPU_LEVEL1_DCACHE_LINESIZE)));

public:
  Stage_manager()
  {
  }

  ~Stage_manager()
  {
  }

  /**
     Constants for queues for different stages.
   */
  enum StageID {
    FLUSH_STAGE,
    SYNC_STAGE,
    COMMIT_STAGE,
    STAGE_COUNTER
  };


/**
  Commit the transaction in the transaction coordinator.

  This function will commit the sessions transaction in the binary log
  and in the storage engines (by calling @c ha_commit_low). If the
  transaction was successfully logged (or not successfully unlogged)
  but the commit in the engines did not succed, there is a risk of
  inconsistency between the engines and the binary log.

  For binary log group commit, the commit is separated into three
  parts:

  1. First part consists of filling the necessary caches and
     finalizing them (if they need to be finalized). After this,
     nothing is added to any of the caches.

  2. Second part execute an ordered flush and commit. This will be
     done using the group commit functionality in ordered_commit.

  3. Third part checks any errors resulting from the ordered commit
     and handles them appropriately.

  @retval RESULT_SUCCESS   success
  @retval RESULT_ABORTED   error, transaction was neither logged nor committed
  @retval RESULT_INCONSISTENT  error, transaction was logged but not committed
*/

個人理解:
在每次commit的時候會觸發組提交,那組提交是分flush sync commit,就是說上一個提交在執行的時候,會累計當前組的事務,當前組的事務數取決與上個事務提交的速度,如果上個事務提交的慢,累計的事務多,下次的組提交的事務數就越多
在sync階段有2個參數控制一組事務的多少,但是不是具體值。
binlog_group_commit_sync_delay=N:在等待N μs後,開始事務刷盤(圖中Sync binlog)
binlog_group_commit_sync_no_delay_count=N:如果隊列中的事務數達到N個,就忽視binlog_group_commit_sync_delay的設置,直接開始刷盤

flush階段是redo log的組提交,這個是刷redo 到磁盤,sync階段是binlog的組提交,這個階段確定了事務的存在,commit階段是引擎層的提價。詳細參考:https://blog.csdn.net/n88Lpo/article/details/81187372

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章