溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Mysql 5.7中mysql.gtid_executed表及其他變量更改時機(jī)是什么

發(fā)布時間:2021-11-12 14:41:12 來源:億速云 閱讀:147 作者:iii 欄目:MySQL數(shù)據(jù)庫

本篇內(nèi)容介紹了“Mysql 5.7中mysql.gtid_executed表及其他變量更改時機(jī)是什么”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

一、主庫修改時機(jī)

(2) binlog打開
  • mysql.gtid_executed表修改時機(jī)

在binlog發(fā)生切換(rotate)的時候保存直到上一個binlog文件執(zhí)行過的全部Gtid,它不是實(shí)時更新的。
棧幀如下:

#0  Gtid_table_persistor::save (this=0x2f9f9c0, gtid_set=0x7ffff03595a0) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_persist.cc:425
#1  0x0000000001803dbe in Gtid_state::save (this=0x2ff8bb0, gtid_set=0x7ffff03595a0) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_state.cc:796
#2  0x0000000001803f62 in Gtid_state::save_gtids_of_last_binlog_into_table (this=0x2ff8bb0, on_rotation=true)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_state.cc:835
#3  0x000000000185266d in MYSQL_BIN_LOG::new_file_impl (this=0x2dffc80, need_lock_log=false, extra_description_event=0x0)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:6751
#4  0x00000000018520a7 in MYSQL_BIN_LOG::new_file_without_locking (this=0x2dffc80, extra_description_event=0x0)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:6636
#5  0x0000000001853e67 in MYSQL_BIN_LOG::rotate (this=0x2dffc80, force_rotate=true, check_purge=0x7ffff0359c4b)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:7292

其主要邏輯在Gtid_state::save_gtids_of_last_binlog_into_table 中我們在隨后的部分討論這個函數(shù)邏輯。

  • gtid_executed變量修改時機(jī)

如前文所述ordered_commit flush階段生成Gtid,在commit階段才計入gtid_executed變量,它是實(shí)時更新的。
棧幀如下:

#0  Gtid_set::_add_gtid (this=0x2ff8d38, sidno=1, gno=16) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid.h:1135
#1  0x0000000001804576 in Gtid_set::_add_gtid (this=0x2ff8d38, gtid=...) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid.h:1166
#2  0x00000000018024ba in Gtid_state::update_gtids_impl (this=0x2ff8bb0, thd=0x7fff2c000b70, is_commit=true)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_state.cc:304
#3  0x00000000018020df in Gtid_state::update_on_commit (this=0x2ff8bb0, thd=0x7fff2c000b70) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_state.cc:148
#4  0x00000000018573d4 in MYSQL_BIN_LOG::process_commit_stage_queue (this=0x2dffc80, thd=0x7fff2c000b70, first=0x7fff2c000b70)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:8646
#5  0x0000000001858b51 in MYSQL_BIN_LOG::ordered_commit (this=0x2dffc80, thd=0x7fff2c000b70, all=false, skip_commit=false)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:9304

其主要邏輯在Gtid_state::update_gtids_impl中我們在隨后的部分討論這個函數(shù)邏輯。

  • gtid_purged變量修改時機(jī)

在Mysql觸發(fā)的清理binlog的情況下,比如purge binary logs to或者超過參數(shù)expire_logs_days設(shè)置的天數(shù)后自動刪除,需要將丟失的Gtid計入這個變量中。
棧幀如下:

#0  MYSQL_BIN_LOG::init_gtid_sets (this=0x2e00280, all_gtids=0x0, lost_gtids=0x2fcaee8, verify_checksum=false, need_lock=false, trx_parser=0x0, gtid_partial_trx=0x0, is_server_starting=false)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:4333
#1  0x0000000001850b8e in MYSQL_BIN_LOG::purge_logs (this=0x2e00280, to_log=0x7fff57a74ad0 "/root/mysql5.7.14/percona-server-5.7.14-7/mysql-test/var/mysqld.1/test.000202", included=false, need_lock_index=true, 
    need_update_threads=true, decrease_log_space=0x0, auto_purge=false) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:6036
#2  0x0000000001848ecf in purge_master_logs (thd=0x7fff49200dc0, to_log=0x7fff492051a8 "test.000202") at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:2815

其主要邏輯在MYSQL_BIN_LOG::purge_logs中,我們隨后查看其代碼片段,同時MYSQL_BIN_LOG::init_gtid_sets函數(shù)是一個及其重要的函數(shù),主要用在:

  • Mysql啟動時候初始化整個Gtid_state中的各種Gtid_set。

  • Mysql刪除binlog(如purge binary logfiles或者超過expire_logs_days設(shè)置)后需要確認(rèn)gtid_purged變量(及Gtid_state.lost_gtids)的值的時候。

隨后我會單獨(dú)一節(jié)來講解Mysql Gtid模塊的初始化還會講解這個函數(shù)。

二、主庫修改時機(jī)源碼函數(shù)分析

這里就對上面提到的主要邏輯函數(shù)進(jìn)行分析

  • Gtid_state::save_gtids_of_last_binlog_into_table函數(shù)邏輯

logged_gtids_last_binlog.add_interval_memory(PREALLOCATED_INTERVAL_COUNT, iv); //這里構(gòu)建一個logged_gtids_last_binlog集合來保存切換后需要寫入表和previous_gtids_logged的Gtid
  /*
    logged_gtids_last_binlog= executed_gtids - previous_gtids_logged -
                              gtids_only_in_table
  */
  global_sid_lock->wrlock();//
  ret= (logged_gtids_last_binlog.add_gtid_set(&executed_gtids) !=  //將當(dāng)前執(zhí)行過的Gtid全部加入logged_gtids_last_binlog 列如:executed_gtids start=1, end=27 
        RETURN_STATUS_OK);
  if (!ret)
  {
    logged_gtids_last_binlog.remove_gtid_set(&previous_gtids_logged); //獲得上一個binlog文件包含的全部Gtid,并且做一個差集 列如:previous_gtids_logged 為start=1, end=25
                                                                      //做完差集后logged_gtids_last_binlog為start=26, end=27
    logged_gtids_last_binlog.remove_gtid_set(&gtids_only_in_table);//此處主庫一定為空,除非異常情況
    if (!logged_gtids_last_binlog.is_empty()) 
    {
      /* Prepare previous_gtids_logged for next binlog on binlog rotation */
      if (on_rotation)
        ret= previous_gtids_logged.add_gtid_set(&logged_gtids_last_binlog);//將這個start=26, end=27的Gtid集合加入到previous_gtids_logged中,這樣previous_gtids_logged也完整了
      global_sid_lock->unlock();
      /* Save set of GTIDs of the last binlog into gtid_executed table */
      if (!ret)
        ret= save(&logged_gtids_last_binlog);//將這個start=26, end=27的Gtid集合寫入到表mysql.gtid_executed表中
    }
  • Gtid_state::update_gtids_impl函數(shù)代碼片段

while (g.sidno != 0)
    {
      if (g.sidno != prev_sidno)
        sid_locks.lock(g.sidno);
      owned_gtids.remove_gtid(g); //從owned_gtid中去掉
      git.next();
      g= git.get();
      if (is_commit)
        executed_gtids._add_gtid(g);//將這個Gtid加入到executed_gtids
    }
  • MYSQL_BIN_LOG::purge_logs函數(shù)代碼片段

if (!is_relay_log)
  {
    global_sid_lock->wrlock();
    error= init_gtid_sets(NULL,
                          const_cast<Gtid_set *>(gtid_state->get_lost_gtids()),
                          opt_master_verify_checksum,
                          false/*false=don't need lock*/,
                          NULL/*trx_parser*/, NULL/*gtid_partial_trx*/);//這里我看到將gtid_state->lost_gtids直接傳入給了init_gtid_sets
                                                                        //init_gtid_sets會做正向查找獲得gtid_state->lost_gtids這個函數(shù)稍后
                                                                        //詳細(xì)討論
    global_sid_lock->unlock();
    if (error)
      goto err;
  }

三、從庫修改時機(jī)

(2)binlog開啟同時參數(shù)log_slave_updates開啟的情況

這種情況sql_thread執(zhí)行過的Gtid事物可以通過binlog進(jìn)行維護(hù),所以mysql.gtid_executed表和gtid_purged變量不需要實(shí)時更新。

  • mysql.gtid_executed表修改時機(jī)

和主庫一致。及在進(jìn)行日志切換的時候進(jìn)行更新,不做討論

  • gtid_executed變量修改時機(jī)

和主庫一樣實(shí)時更新,不做討論

  • gtid_purged變量修改時機(jī)

和主庫一致,binlog刪除時更新,不做討論

四、從庫修改時機(jī)源碼函數(shù)分析

  • commit_owned_gtids函數(shù)邏輯:

//如果 binlog 沒有開啟包括(log_bin=0 和 sql_log_bin =0 )或者 開啟了binlog 但是slave線程并且slave update 沒有開啟,都會記錄gtid到表
//但是這里要注意一點(diǎn)在主庫上如果binlog不開啟那么thd->owned_gtid.sidno ==0 因為這個時候Gtid都沒有生成,生成階段為order_commit的commit階段
  if ((!opt_bin_log || (thd->slave_thread && !opt_log_slave_updates)) && 
      (all || !thd->in_multi_stmt_transaction_mode()) && //all 代表是否是顯示begin 事物 in_multi_stmt_transaction_mode則相反
      !thd->is_operating_gtid_table_implicitly && //是否是GTID_NEXT方式 flase
      !thd->is_operating_substatement_implicitly)//是否是子語句 flase
  {
    /*
      If the binary log is disabled for this thread (either by
      log_bin=0 or sql_log_bin=0 or by log_slave_updates=0 for a
      slave thread), then the statement will not be written to
      the binary log. In this case, we should save its GTID into
      mysql.gtid_executed table and @@GLOBAL.GTID_EXECUTED as it
      did when binlog is enabled.
    */
    if (thd->owned_gtid.sidno > 0)
    {
      error= gtid_state->save(thd);//就是這里進(jìn)行了mysql.gtid_executed表的實(shí)時更新
      *need_clear_owned_gtid_ptr= true;
    }
    else if (thd->owned_gtid.sidno == THD::OWNED_SIDNO_ANONYMOUS)
      *need_clear_owned_gtid_ptr= true;
  }
  • Gtid_state::update_gtids_impl_own_gtid 函數(shù)邏輯片段
    這個函數(shù)是5.7.17的,5.7.14沒有邏輯放到了Gtid_state::update_gtids_impl中

if (is_commit)
  {
    DBUG_EXECUTE_IF(
      "rpl_gtid_update_on_commit_simulate_out_of_memory",
      DBUG_SET("+d,rpl_gtid_get_free_interval_simulate_out_of_memory"););
    /*
      Any session adds transaction owned GTID into global executed_gtids.

      If binlog is disabled, we report @@GLOBAL.GTID_PURGED from
      executed_gtids, since @@GLOBAL.GTID_PURGED and @@GLOBAL.GTID_EXECUTED
      are always same, so we did not save gtid into lost_gtids for every
      transaction for improving performance.

      If binlog is enabled and log_slave_updates is disabled, slave
      SQL thread or slave worker thread adds transaction owned GTID
      into global executed_gtids, lost_gtids and gtids_only_in_table.
    */
    executed_gtids._add_gtid(thd->owned_gtid); //加入executed_gtids集合
    thd->rpl_thd_ctx.session_gtids_ctx().
      notify_after_gtid_executed_update(thd);
    if (thd->slave_thread && opt_bin_log && !opt_log_slave_updates)//如果是slave線程同時binlog開啟了并且log_slave_updates關(guān)閉了
                                                                   //如果binlog關(guān)閉則使用 executed_gtids這樣提高性能前面的注釋說了
    {
      lost_gtids._add_gtid(thd->owned_gtid);  //寫入lost_gtids也就是更新參數(shù)gtid_purged變量
      gtids_only_in_table._add_gtid(thd->owned_gtid);
    }
  }

五、通用更改時機(jī)

mysql.gtid_executed表修改時機(jī)

  • 在reset master的時候清空本表
    棧幀如下:

#0  Gtid_table_persistor::delete_all (this=0x2f9f9c0, table=0x7fff2c0116a0) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_persist.cc:795
#1  0x000000000180a4ef in Gtid_table_persistor::reset (this=0x2f9f9c0, thd=0x7fff2c000b70) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_persist.cc:689
#2  0x0000000001801f2e in Gtid_state::clear (this=0x2ff8bb0, thd=0x7fff2c000b70) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_state.cc:36
#3  0x000000000184fee6 in MYSQL_BIN_LOG::reset_logs (this=0x2dffe80, thd=0x7fff2c000b70, delete_only=false)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:5586
#4  0x0000000001872308 in reset_master (thd=0x7fff2c000b70) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_master.cc:587

其主要邏輯在Gtid_state::clear中。

  • 在set global gitd_purged的時候,設(shè)置本表
    棧幀如下:

#0  Gtid_table_persistor::save (this=0x2f9f9c0, gtid_set=0x7ffff0359a70) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_persist.cc:425
#1  0x000000000180400a in Gtid_state::save (this=0x2ff8bb0, gtid_set=0x7ffff0359a70) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_state.cc:796
#2  0x0000000001803c25 in Gtid_state::add_lost_gtids (this=0x2ff8bb0, gtid_set=0x7ffff0359a70) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_state.cc:737
#3  0x00000000016778f3 in Sys_var_gtid_purged::global_update (this=0x2de9fe0, thd=0x7fff2c000b70, var=0x7fff2c006630)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/sys_vars.cc:5888
#4  0x00000000014d5cd1 in sys_var::update (this=0x2de9fe0, thd=0x7fff2c000b70, var=0x7fff2c006630) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/set_var.cc:184
#5  0x00000000014d74ee in set_var::update (this=0x7fff2c006630, thd=0x7fff2c000b70) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/set_var.cc:812
#6  0x00000000014d6d1a in sql_set_variables (thd=0x7fff2c000b70, var_list=0x7fff2c003528) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/set_var.cc:669

其主要邏輯在Gtid_state::add_lost_gtids中。

gtid_executed變量修改時機(jī)

  • 在reset master的時候清空本變量
    棧幀同上

  • 在set global gitd_purged的時候,設(shè)置本變量
    棧幀同上

  • 在mysql啟動的時候初始化設(shè)置gtid_executed變量,這個將在后面章節(jié)詳細(xì)描述描述步驟。

gtid_purged變量修改時機(jī)

  • 在reset master的時候清空本變量
    棧幀同上

  • 在set global gitd_purged的時候,設(shè)置本變量
    棧幀同上

  • 在mysql啟動的時候初始化設(shè)置gtid_executed變量,這個將在后面章節(jié)詳細(xì)描述描述步驟。

六、通用更改時機(jī)源碼函數(shù)分析

  • Gtid_state::clear函數(shù)邏輯

int Gtid_state::clear(THD *thd)
{
 ....
  // the wrlock implies that no other thread can hold any of the mutexes
  sid_lock->assert_some_wrlock();
  lost_gtids.clear();//此處清空gtid_purged變量
  executed_gtids.clear();//此處清空gtid_executed變量
  gtids_only_in_table.clear();//清空only in table Gtid set
  previous_gtids_logged.clear();//清空 previous gtids logged Gtid set
  /* Reset gtid_executed table. */
  if ((ret= gtid_table_persistor->reset(thd)) == 1)//此處清空mysql.gtid_executed表
  {
    /*
      Gtid table is not ready to be used, so failed to
      open it. Ignore the error.
    */
    thd->clear_error();
    ret= 0;
  }
  next_free_gno= 1;
  DBUG_RETURN(ret);
}
  • Gtid_state::add_lost_gtids函數(shù)邏輯

enum_return_status Gtid_state::add_lost_gtids(const Gtid_set *gtid_set)
{
  ......
  if (save(gtid_set)) //此處將set gtid_purge的值加入到mysql.gtid_executed表中
    RETURN_REPORTED_ERROR;
  PROPAGATE_REPORTED_ERROR(gtids_only_in_table.add_gtid_set(gtid_set));
  PROPAGATE_REPORTED_ERROR(lost_gtids.add_gtid_set(gtid_set));//此處將set gtid_purge的值加入到gtid_purge變量中
  PROPAGATE_REPORTED_ERROR(executed_gtids.add_gtid_set(gtid_set));//此處將set gtid_purge的值加入到gtid_executed變量中
  lock_sidnos(gtid_set);
  broadcast_sidnos(gtid_set);
  unlock_sidnos(gtid_set);
  DBUG_RETURN(RETURN_STATUS_OK);
}

“Mysql 5.7中mysql.gtid_executed表及其他變量更改時機(jī)是什么”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI