MySQL slave中繼日志損壞修復方案

      網友投稿 953 2025-04-03

      Contents

      1??? 背景... 2

      2????Relay log的獲取與應用... 2

      2.1?????? 源碼分析... 2

      2.1.1??? 配置參數relay_log_recovery=OFF重啟后,slave機制與源碼... 2

      2.1.2??? 配置參數relay_log_recovery=ON重啟后,slave機制與源碼... 3

      3?????修復計劃... 4

      3.1??具體實現思路... 4

      3.2???流程圖... 5

      4???總結... 5

      1???????? 背景

      MySQL的Crash safe slave是指slave crash后,把slave重新拉起來可以繼續從Master進行復制,不會出現復制錯誤也不會出現數據不一致。為保證crash safe slave,需解決由于未同步刷盤導致的binlog文件接收位置和實際不一致或者relay log文件不完整的問題,因此relay_log_recovery為ON是必需配置參數之一。但是設置relay_log_recovery為ON會導致MySQL正常重啟或者宕機恢復時以備庫的SQL線程執行位置為起點重新向主庫請求binlog,可能由于之前主備時延大,請求點的binlog已被主機清除,最終導致主備復制關系異常,因此設置relay_log_recovery為OFF是生產環境常見的設置。但是,此設置在OS的oom-killer事件以及OS異常斷電等情況可能導致備庫relay log的部分event不完整, MySQL重啟后,SQL線程回放執行到不完整的event就會導致主備復制關系中斷,查看error.log可以看到類似如下的錯誤信息:

      2???????? Relay log的獲取與應用

      MySQL支持的復制方式按連接協議來區分,可以分為

      ???? 非GTID模式,通過binlog文件名和文件的偏移來決定復制位點信息

      ???? GTID模式,通過GTID信息來決定復制位點信息

      2.1???????? 源碼分析

      2.1.1??????? 配置參數relay_log_recovery=OFF重啟后,slave機制與源碼

      1)基于binlog復制(非GTID)模式,MySQL重啟后,重連主庫時,備庫的IO線程讀取slave_master_info表記錄的master_log_name以及master_log_pos值向主庫請求binlog。

      1.? |-init_slave()

      2.? /*?read?all?the?slave?repositories?on?disk?(either?in?FILE?or?TABLE?form)?and?create?corresponding?slave?info?objects

      3.? */

      4.? ??|-Rpl_info_factory::create_slave_info_objects

      5.? ?????|-load_mi_and_rli_from_repositories

      6.? ???????|-Master_info::mi_init_info()

      7.? /*?Creates?or?reads?information?from?the?repository,?initializing?the?Master_info.*/

      8.? ?????????|-Master_info::read_info()

      9.? ???????????|-get_info()

      10. ???????????//初始化mi?master_log_pos?&&?master_log_name

      備庫的SQL線程讀取slave_relay_log_info表記錄的relay_log_name以及relay_log_pos值開始應用relay log。

      1.? |-init_slave()

      2.? ???|-Rpl_info_factory::create_slave_info_objects

      3.? ?????|-load_mi_and_rli_from_repositories

      4.? ???????|-Relay_log_info::rli_init_info

      5.? ?????????|-Relay_log_info::read_info()

      6.? ?????????//rli?group_relay_log_pos?&&?group_master_log_pos?&&

      7.? ?????????group_relay_log_name?&&?group_master_log_name

      2)基于GTID復制模式,MySQL重啟后,重連主庫時,備庫的IO線程通過讀取mysql.gtid_executed表以及binlog文件獲取Executed_Gtid_Set,通過讀取realy_log文件獲取Retrieved_Gtid_Set,并將兩者的并集發送到主庫請求binlog。

      1.? mysqld_main?()

      2.? ?//讀持久化介質mysql.gtid_executed表

      3.? ?|-Gtid_state::read_gtid_executed_from_table?()

      4.? ?//讀持久化介質binlog

      5.? ?|-MYSQL_BIN_LOG::init_gtid_sets?()

      MySQL slave中繼日志損壞修復方案

      6.? ?|-init_slave?()

      7.? ??|-Rpl_info_factory::create_slave_info_objects?()

      8.? ???|-load_mi_and_rli_from_repositories?()

      9.? ????|-Relay_log_info::rli_init_info?()

      10. ?????|-MYSQL_BIN_LOG::init_gtid_sets?()

      11. ??????|-Relay_log_info::init_relay_log_pos?()

      對于備庫的SQL線程其應用relay log的起始從slave_relay_log_info表讀取,其執行過程如果發現事務的gtid已經存在,則ev->apply_event時就會忽略這個事務,保證不會重復執行同一個事務。

      2.1.2??????? 配置參數relay_log_recovery=ON重啟后,slave機制與源碼

      當參數relay_log_recovery為ON,不論是單線程還是多線程回放,MySQL正常重啟或者宕機恢復時以備庫的SQL線程執行位置為起點重新向主庫請求binlog。基于binlog復制發送的是slave_relay_log_info表讀取relay_log_name以及Relay_log_pos值?;贕TID復制模式發送的是備庫執行完的gtid_sets。

      1.? static?void?recover_relay_log(Master_info?*mi)

      2.? {

      3.? ??Relay_log_info?*rli=mi->rli;

      4.? ??//?Set?Receiver?Thread's?positions?as?per?the?recovered?Applier?Thread.

      5.? ??mi->set_master_log_pos(max(BIN_LOG_HEADER_SIZE,

      6.? ????????????????????????????????????????rli->get_group_master_log_pos()));

      7.? ??mi->set_master_log_name(rli->get_group_master_log_name());

      8.? ??rli->set_group_relay_log_name(rli->relay_log.get_log_fname());

      9.? ??rli->set_event_relay_log_name(rli->relay_log.get_log_fname());

      10. ??rli->set_group_relay_log_pos(BIN_LOG_HEADER_SIZE);

      11. ??rli->set_event_relay_log_pos(BIN_LOG_HEADER_SIZE);

      12. }

      3????? 修復計劃

      當備庫配置master_info_repository與relay_log_info_repository都為TABLE時,對于SQL線程而言,會在一個事務提交的同時更新表slave_relay_log_info,其得到原子性保證,即SQL線程執行位置始終是對的。但異常宕機可能導致丟失master info,IO線程會dump到重復的日志和SQL線程可能會重復執行同一個事務,這樣就會導致主備復制出錯,這樣對于非gtid復制的模式,所以為保證主備正常且數據一致,relay_log_recovery=ON為Crash safe slave必需參數。

      但是如果開啟了gtid就可以避免上述問題,GTID復制協議保證了數據的一致性,且ev->apply_event時會忽略已執行的事務。因此對于備庫設置為relay_log_recovery=OFF的配置,relay log文件中可能存在的損壞的event可直接清除,避免出現主備復制關系異常。

      3.1????? 具體實現思路

      方案:

      1、在MySQL啟動初始化過程中進行損壞relay log(不完整event)修復。

      2、在初始化Gtid_sets的MYSQL_BIN_LOG:init_gtid_set()處,若配置參數設置了功能啟動開關rds_recovery_relay_log=ON,則進入下面流程。

      3、掃描relay log時,判斷其是否是正常關閉,非正常關閉則進入修復檢測流程。

      4、讀取非正常關閉relay log文件,遍歷其event,并記錄更新合法的event的位置,若存在非完整event則退出,返回記錄的最新合法event位置。

      4、根據返回的合法event位置截斷relay log,清除文件中損壞的部分。

      5、后續流程正常進行

      3.2????? 流程圖

      4????? 總結

      設置rds_relay_log_recovery參數設置為ON,可解決OS宕機等情況導致MySQL備庫的relay log的不完整導致主備異常情況。建議使用方法,在OS宕機等情況,重啟mysql服務時,設置開啟rds_relay_log_recovery=ON,可預防relay_log_recovery=ON的潛在缺點即自sql thread執行完的gtid起請求的binlog已被master purge。

      任務調度 MySQL

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:Excel表格中如何制作一個柱形動態圖表
      下一篇:Excel數據驗證 表格內容填錯萬事不求人(excel數據驗證自定義怎么用)
      相關文章
      亚洲精品国产成人| 亚洲香蕉在线观看| 亚洲精品精华液一区二区| 91亚洲精品麻豆| 亚洲妓女综合网99| 亚洲综合综合在线| 亚洲男人在线无码视频| 亚洲国产成人久久综合野外| www.91亚洲| 亚洲免费视频一区二区三区| 亚洲精品tv久久久久久久久久| 国产V亚洲V天堂无码| 亚洲成亚洲乱码一二三四区软件| 国产亚洲成av片在线观看| 国产亚洲成av片在线观看| 亚洲国产天堂久久久久久| 亚洲AV无一区二区三区久久| 亚洲av午夜福利精品一区| 亚洲综合无码一区二区| 亚洲精品永久www忘忧草| 亚洲国产高清在线精品一区| 亚洲国产精品久久久久秋霞小| 亚洲爆乳少妇无码激情| 久久久久久亚洲精品无码| 国产亚洲精品成人久久网站| 亚洲视频在线免费| 亚洲入口无毒网址你懂的| 亚洲精品乱码久久久久久蜜桃图片| 国产精品无码亚洲精品2021| 亚洲成?Ⅴ人在线观看无码| 久久亚洲av无码精品浪潮| 亚洲av最新在线观看网址| 久久亚洲精品成人无码| ZZIJZZIJ亚洲日本少妇JIZJIZ| 亚洲日韩精品无码一区二区三区| 午夜亚洲AV日韩AV无码大全| 亚洲电影唐人社一区二区| 7777久久亚洲中文字幕蜜桃| 亚洲一区中文字幕| 亚洲AV噜噜一区二区三区| 青青草原亚洲视频|