MySQL 5.7 並行複製源碼分析

目錄

1. 基礎數據結構

2. 處理邏輯

2.1 Prepare階段存儲本事務的last_commit

2.2 Commit第三階段更新全局的m_max_committed_transaction

2.3 Flush階段獲取事務的sequence_number


1. 基礎數據結構

添加全局的事務計數器產生事務timestamp和記錄當前最大事務timestamp的clock。

每個BinLog文件對應一對,代碼關係爲:

class MYSQL_BIN_LOG: public TC_LOG

=>Transaction_dependency_tracker => Commit_order_trx_dependency_tracker

class MYSQL_BIN_LOG: public TC_LOG
{
  ...
  public:
  /* Committed transactions timestamp */
  Logical_clock max_committed_transaction;
  /* "Prepared" transactions timestamp */
  Logical_clock transaction_counter;
  ...
}
class  Logical_clock
{
private:
  int64 state;
  /*
    Offset is subtracted from the actual "absolute time" value at
    logging a replication event. That is the event holds logical
    timestamps in the "relative" format. They are meaningful only in
    the context of the current binlog.
    The member is updated (incremented) per binary log rotation.
  */
  int64 offset;
public:
  Logical_clock();
  int64 step();
  int64 set_if_greater(int64 new_val);
  int64 get_timestamp();
  int64 get_offset() { return offset; }
  /*
    Updates the offset.
    This operation is invoked when binlog rotates and at that time
    there can't any concurrent step() callers so no need to guard
    the assignement.
  */
  void update_offset(int64 new_offset)
  {
    DBUG_ASSERT(offset <= new_offset);

    offset= new_offset;
  }
};

state是一個自增的值,offset在每次二進制日誌發生rotate時更新,記錄發生rotate時的state值。其實state和offset記錄的是全局的計數值,而存在二進制日誌中的僅是當前文件的相對值。

 

對每個事務定義其lock interval,並記錄到binlog中,在每個transaction中添加下面兩個member。

class Transaction_ctx
{
  ...
  /*
    Store for the transaction's commit parent sequence_number.
    The value specifies this transaction dependency with a "parent"
    transaction.
    The member is assigned, when the transaction is about to commit
    in binlog to a value of the last committed transaction's sequence_number.
    This and last_committed as numbers are kept ever incremented
    regardless of binary logs being rotated or when transaction
    is logged in multiple pieces.
    However the logger to the binary log may convert them
    according to its specification.
  */
  int64 last_committed;
  /*
    The transaction's private logical timestamp assigned at the
    transaction prepare phase. The timestamp enumerates transactions
    in the binary log. The value is gained through incrementing (stepping) a
    global clock.
    Eventually the value is considered to increase max_committed_transaction
    system clock when the transaction has committed.
  */
  int64 sequence_number;
  ...
}

 

2. 處理邏輯

2.1 Prepare階段存儲本事務的last_commit

從BinLog對象中取出m_max_committed_transaction,存儲到(Transaction_ctx)Trx_ctx的last_committed中。

static int binlog_prepare(handlerton *hton, THD *thd, bool all)
{
  DBUG_ENTER("binlog_prepare");
  if (!all)
  {
    thd->get_transaction()->store_commit_parent(mysql_bin_log.
      m_dependency_tracker.get_max_committed_timestamp());

  }

  DBUG_RETURN(all && is_loggable_xa_prepare(thd) ?
              mysql_bin_log.commit(thd, true) : 0);
}

 

2.2 Commit第三階段更新全局的m_max_committed_transaction

    if (head->get_transaction()->sequence_number != SEQ_UNINIT)
    {
      mysql_mutex_lock(&LOCK_slave_trans_dep_tracker);
      m_dependency_tracker.update_max_committed(head);
      mysql_mutex_unlock(&LOCK_slave_trans_dep_tracker);
    }

------
void
Transaction_dependency_tracker::update_max_committed(THD *thd)
{
  Transaction_ctx *trn_ctx= thd->get_transaction();
  m_commit_order.update_max_committed(trn_ctx->sequence_number);
  /*
    sequence_number timestamp isn't needed anymore, so it's cleared off.
  */
  trn_ctx->sequence_number= SEQ_UNINIT;

  DBUG_ASSERT(trn_ctx->last_committed == SEQ_UNINIT ||
              thd->commit_error == THD::CE_FLUSH_ERROR);
}

 

2.3 Flush階段獲取事務的sequence_number

binlog_cache_data::flush(THD *thd, my_off_t *bytes_written, bool *wrote_xid)
{
    Transaction_ctx *trn_ctx= thd->get_transaction();
    trn_ctx->sequence_number= mysql_bin_log.m_dependency_tracker.step();

    mysql_bin_log.write_gtid(thd, this, &writer)
}

------

return m_transaction_counter.step();
return ++state;

 

https://www.jianshu.com/p/8c416f3f471b

https://www.cnblogs.com/xiaotengyi/p/5532191.html

https://blog.csdn.net/andong154564667/article/details/82117727

http://mysql.taobao.org/monthly/2017/12/03/

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