【小資說庫】第13期 應用程序開發人員、DBA和DBMS開發人員的分工是怎樣的?
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?()
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
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小時內刪除侵權內容。