[MySQL FAQ]系列 — 5.6版本GTID複製異常處理一例

2021-02-08 老葉茶館

昨天處理了一個MySQL 5.6版本下開啟GTID模式複製異常案例,MASTER上的任何操作都無法在SLAVE上應用,SLAVE的RELAY LOG裡有記錄,但SLAVE的BINLOG卻找不到蛛絲馬跡。由於開啟了GTID,所以排查起來也簡單,只需要在SLAVE上把RELAY LOG和BINLOG分別解析成文本文件,再直接搜索MASTER的UUID,就能找到SLAVE上是否應用了MASTER複製過來的事務。 排查過程中,曾經一度懷疑是因為設置了BINLOG-DO或者IGNORE規則,或者設置了REPLICATION-DO或IGNORE規則,甚至是GTID的嚴重BUG,但都沒發現端倪。直到從 SHOW SLAVE STATUS 裡發現下面這個信息:

[yejr@imysql.com]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
... Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 2539
Relay_Log_File: mysql-relay-bin.000003
Relay_Log_Pos: 1996
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
# 兩個線程工作正常
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
#沒設置任何規則
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 2539
# 無論binlog file 還是 pos,都和MASTER保持一致,也就是說BINLOG的接收和RELAYR LOG的APPLY都很正常,有條不紊工作著
Relay_Log_Space: 2778
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
...
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
# 沒設置忽略某些 server-id 上的BINLOG
Master_Server_Id: 123315
Master_UUID: 35cc99c6-0297-11e4-9916-782bcb2c9453
Master_Info_File: /data/db11_3316/master.info
SQL_Delay: 0
# 沒有設置複製延遲策略
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
Master_Retry_Count: 4294967295
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set: 35cc99c6-0297-11e4-9916-782bcb2c9453:1-451
Executed_Gtid_Set: 35cc99c6-0297-11e4-9916-782bcb2c9453:1-2455:792490-4517929
Auto_Position: 1

從上面的日誌發現什麼了沒?尤其是這兩行:

Retrieved_Gtid_Set: 35cc99c6-0297-11e4-9916-782bcb2c9453:1-451
Executed_Gtid_Set: 35cc99c6-0297-11e4-9916-782bcb2c9453:1-2455:792490-4517929
Auto_Position: 1

這下有點明白了吧,意思是:

1、SLAVE從MASTER上複製了GTID範圍是:1-451;
2、SLAVE上執行GTID的範圍氛圍兩段,一段是:1-2455,另一段是:792490-4517929;

尼瑪,不應該是連續的嘛,怎麼會這麼奇葩⊙﹏⊙b,這可如何是好呀,好捉急~~~ 莫急,且容我們慢慢分析為啥GTID從MASTER到SLAVE之後發生了斷點,產生了間隙。

正常滴,在MySQL 5.6啟用GTID後,部署REPLICATION複製時,可以設定 MASTER_AUTO_POSITION = 1,讓 SLAVE 根據 GTID 自動選擇適當的事務點進行複製,DBA基本上無需關注和擔心主從不一致的問題,還是很讓DBA省心的。 在啟用 MASTER_AUTO_POSITION = 1 的情況下,正常是不會發生 GTID 中間有個空隙,產生斷點的問題發生。除非是下面這種情況:

1、人工暫停SLAVE進程;
2、MASTER上繼續寫入數據;
3、MASTER上刷新LOG;
4、MASTER上刪除舊BINLOG,只保留最新的BINLOG;
5、SLAVE上啟動MASTER,這時候會報錯,像下面這樣:
Last_IO_Errno: 1236
Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.'

針對這種問題的處理方法可以這麼做:

1、關閉MASTER_AUTO_POSITION,即設置 MASTER_AUTO_POSITION = 0;
2、手工CHANGE BINLOG FILE & POS;

這種情況下,不能再次設置 MASTER_AUTO_POSITION = 1,否則還會再次報錯。 還有一種情況會發生 GTID 間隙斷點問題,例如這樣:

1、正常配置 REPLICATION 複製,但是設置 MASTER_AUTO_POSITION = 0,也就是人工指定 BINLOG FILE & POS的傳統方法;
2、在複製過程中,暫時關閉 SLAVE 進程;
3、手工修改 BINLOG FILE & POS 信息,指向新的 BINLOG FILE & POS 點;
4、啟動SLAVE,這時候就會發現 GTID 斷點的現象重現了;

在主從高可用模式下,可能主從間會發生切換,然後再次切換回來,這時候也可能發生上述的斷點問題。因此我們建議採用雙主來部署高可用切換,基本上可以實現任意來回切換,無需手工指定新的 BINLOG FIEE & POS 信息。

還有最後一種情況,就是在 MASTER 上執行了 RESET MASTER,導致 MASTER 上的 BINLOG FILE & POS 全部重置,SLAVE 上讀取到的信息自然也就不一致了。

好了,說了那麼多,我們最後來說下如何應對處理 GTID 斷點的問題。

方法一:手工修改 BINLOG FILE & POS

1、關閉SLAVE;
2、手工CHANGE BINLOG FILE & POS,指向MASTER上最新產生的BINLOG FILE & POS,並且設置 MASTER_AUTO_POSITION = 0;
3、啟動SLAVE;

方法二:手工修改 GTID_PURGED 值

1、關閉 SLAVE;
2、在 SLAVE 上執行 RESET MASTER,重設 SLAVE 上的 BINLOG FILE & POS;
3、在 SLAVE 上執行 SET @@GLOBAL.GTID_PURGED = '35cc99c6-0297-11e4-9916-782bcb2c9453:1-2455';
4、啟動 SLAVE;

這種做法比較費解一點,意思是,我們告訴SLAVE要主動拋棄掉 MASTER 上傳輸過來的某些區間的事務。在這個例子中,我們拋棄了 1-2455 這個區間,也就是在 GTID 從 2466 開始,又會繼續應用 RELAY LOG 了,相比我們最開始的那個信息:

Retrieved_Gtid_Set: 35cc99c6-0297-11e4-9916-782bcb2c9453:1-451 Executed_Gtid_Set: 35cc99c6-0297-11e4-9916-782bcb2c9453:1-2455:792490-4517929

我們強制 SLAVE 只忽略 1-2455 這個區間,從 2466 開始繼續複製,消除了本來也會被忽略的區間: 792490-4517929,確保新產生的事務都會被繼續應用。這個做法可以參考MySQL手冊:Excluding transactions with gtid_purged。

還有另外一種費力不討好的做法,就是在 MASTER 上執行一些沒用的空事務,使得 GTID 的序號一直在加大,直到超過 2555 為止,然後在 792490-4517929 這個區間依法炮製一番,但我們非常不推薦採用這種做法,既麻煩又容易誤操作。 說了這麼多,在 MySQL 5.6及以上版本中,我們強烈建議啟用 MASTER_AUTO_POSITION = 1,讓 MySQL 自己去做判斷,減少一些不必要的問題,並且採用雙主(其中一個主設為只讀)的方式,方便兩個主之間可以隨意相互切換,而不必擔心數據不一致。

上面過程我採用的MySQL版本:5.6.17-65.0-rel65.0-log Percona Server with XtraDB (GPL), Release rel65.0, Revision 587,實際案例發生的MySQL版本當時忘了記錄了,但肯定也是5.6以上的啦,哈哈~~~

最後,吐槽下微信公眾號後臺的編輯器,真TMD難用。

===============================================================================

如果還有什麼問題,歡迎加入我的QQ群(125572178、272675472)討論。

===============================================================================

題圖:三國演義

87集的曾仕強《評三國,論智慧》終於還是被我耐心聽完了,彌補了沒有完整看一遍《三國演義》大缺憾,都說少不讀水滸老不讀三國,趁我還沒老去之前,先聽一遍,以後找機會完整看一遍電視劇就好了,看書估計更沒譜了。

總的聽下來,確實獲得了很多智慧,除了三國各路英雄人物讓我無限感慨外,更是對作者羅貫中致以深深的敬意,不愧是四大名著之首,寫的實在太好了,太有智慧了。同事推薦大家也聽聽曾仕強《評三國,論智慧》系列。

相關焦點

  • MySQL 5.7基於GTID及多線程主從複製
    數據安全性由於主庫數據被複製到從庫,從庫可以暫停複製過程,可以在從庫上運行備份服務,而不會破壞對應的主庫數據。分析可以在主庫上創建實時數據,而信息分析可以在從庫上進行,而不會影響主伺服器的性能。Gtid概念從 MySQL 5.6.5 開始新增了一種基於 GTID 的複製方式。
  • 深入理解MySQL 5.7 GTID系列(八):GTID帶來的運維改變
    GTID系列文章共十篇,本文為第四篇,第一篇:深入理解MySQL 5.7 GTID系列(一)第二篇:深入理解MySQL 5.7 GTID系列(二):GTID相關內部數據結構第三篇:深入理解MySQL 5.7 GTID系列(三):GTID的生成時機第四篇:深入理解MySQL
  • 深入理解MySQL 5.7 GTID系列(六):MySQL啟動初始化GTID模塊
    GTID系列文章共十篇,本文為第四篇,第一篇:深入理解MySQL 5.7 GTID系列(一)第二篇:深入理解MySQL 5.7 GTID系列(二):GTID相關內部數據結構第三篇:深入理解MySQL 5.7 GTID系列(三):GTID的生成時機第四篇:深入理解MySQL
  • MySQL GTID(Global Transaction Identifier)深入理解
    GTID是 MySQL 5.6 版本引入的一個有關於主從複製的重大改進,相對於之前版本基於Binlog文件+Position的主從複製,基於GTID的主從複製,數據一致性更高,主從數據複製更健壯,主從切換、故障切換不易出錯,很少需要人為介入處理。
  • MySQL GTID的管理模式
    這是學習筆記的第 1973 篇文章從MySQL 5.6.5 開始新增了一種基於 GTID 的複製方式。
  • 深入理解MySQL 5.7 GTID系列(三):GTID的生成時機
    GTID系列文章共十篇,本文為第三篇,第一篇:深入理解MySQL 5.7 GTID系列(一)第二篇:深入理解MySQL 5.7 GTID系列(二):GTID相關內部數據結構該系列文章將陸續不定期更新~一、GTID生成類型這裡首先使用源碼的解釋給出三種類型:
  • 深入理解MySQL 5.7 GTID系列(二):GTID相關內部數據結構
    GTID系列文章共十篇,本文為第二篇,點擊查看第一篇文章:深入理解MySQL 5.7 GTID系列(一)該系列文章將陸續不定期更新~一、 GTID基本格式 e859a28b-b66d-11e7-8371-000c291f347d:1前一部分是SERVER_UUID,後面一部分是執行事務的唯一標誌,通常是自增的。
  • 操作解析:MySQL如何查看複製信息並排查問題(上)
    本文梳理了UCloud在運維本公司MySQL高可用產品UDB過程中遇到的複製問題,並總結了當複製發生異常時,排查複製異常的方法。錯誤排查1. 收集複製信息在複製發生異常時,首先要分別收集與複製、錯誤相關的信息,主要通過以下手段進行。
  • MySQL- InnoDB之二進位日誌
    2.4 GTID的開啟和配置vim /etc/my.cnfgtid-mode=onenforce-gtid-consistency=true2.5 查看GTID信息mysql> create database gtid charset utf8mb4;mysql> show master status
  • MySQL Binlog 文件格式解析二(GTID_LOG_EVENT)
    insert into tb values(1);解析binlog,執行:show binlog events in 'mysql-bin.000001';可以看到一條插入語句,在binlog中變成了多個event。
  • MySQL基於MHA的FailOver過程
    MHA FailOver過程詳解什麼是FailOver故障轉移主庫宕機,一直到業務恢復正常的處理過程如何處理FailOver1.快速監控到主庫宕機2.選擇新主節點,選擇策略mysqladmin ping檢查資料庫狀態,主機狀態,埠等,判斷從庫節點讀取的master_log_file及read_master_log_pos節點大小,查看Retrieved_gtid_set(已接收到的gtid大小),executed_gtid_set(已執行的
  • MySQL從庫實用技能教程 巧用slave_exec_mode參數
    想必從庫異常中斷的情況不在少數,其中報錯信息中 1032 及 1062 的錯誤佔了不少的比重錯誤 1032 指的是從庫中找不到對應行的記錄錯誤 1062 指的是主鍵衝突遇到此報錯時,大多DBA會使用如下方法進行處理1 手動處理方法一: 找出引起異常的數據然後手動在從庫處理後重啟
  • 主庫n -> 從庫s - MySQL5.7多主一從(多源複製)同步配置 - 計算機...
    多主一從,也稱為多源複製,數據流向:主庫1 -> 從庫s主庫2 -> 從庫s主庫n -> 從庫s應用場景數據匯總,可將多個主資料庫同步匯總到一個從資料庫中,方便數據統計分析。讀寫分離,從庫只用於查詢,提高資料庫整體性能。部署環境註:使用docker部署mysql實例,方便快速搭建演示環境。
  • 技術分享 | MySQL 閃回工具 MyFlash|mysql|session|query|server...
    作者:陳怡愛可生南分團隊 DBA,負責公司自動化運維平臺維護和處理客戶問題。本文來源:原創投稿*愛可生開源社區出品,原創內容未經授權不得隨意使用,轉載請聯繫小編並註明來源。
  • 高性能Mysql主從架構的複製原理及配置詳解
    一旦發現沒法精確複製時, 會自動選著基於行的複製。基於行的複製:把改變的內容複製過去,而不是把命令在從伺服器上執行一遍. 從mysql5.0開始支持混合類型的複製: 默認採用基於語句的複製,一旦發現基於語句的無法精確的複製時,就會採用基於行的複製。
  • [MySQL FAQ]系列 — 怎麼計算打開文件數
    5.6.7(含)以前,默認值0,最大和OS內核限制有關;5.6.8(含)以後,默認值會自動計算,最大和OS內核限制有關。其值最低20,默認400,只計算了包含ibdata*、ib_logfile*、*.ibd 等三類文件,redo log不計算在內,5.6以後可獨立undo log,我還未進行測試,應該也不會被計算在內,有興趣的朋友可驗證下。
  • 技術分享 | MySQL 閃回工具 MyFlash
    作者:陳怡愛可生南分團隊 DBA,負責公司自動化運維平臺維護和處理客戶問題。本文來源:原創投稿*愛可生開源社區出品,原創內容未經授權不得隨意使用,轉載請聯繫小編並註明來源。
  • MySQL主從複製高級進階
    一般企業建議3-6小時,具體看公司運維人員對於故障的反應時間執行之前在需要先stop slave,否則會報錯,無法執行;stop slave;設置master_delay並重新開啟複製start slave後,,MySQL從庫會清空原有的relay log
  • MySQL sql_mode 說明(及處理一起 sql_mode 引發的問題)
    一看,果然:123456mysql> show variables like "sql_mode";++----+| Variable_name | Value                                      |++----+|