【Mysql】Mysql GTID複製程式出現異常,出現斷點

小亮520cl發表於2016-03-10

昨天處理了一個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 裡發現下面這個資訊:

點選(此處)摺疊或開啟

  1. [yejr@imysql.com]> show slave status\G
  2. *************************** 1. row ***************************
  3.                Slave_IO_State: Waiting for master to send event
  4. ... Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 2539 Relay_Log_File: mysql-relay-bin.000003
  5.                 Relay_Log_Pos: 1996 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: Yes
  6.             Slave_SQL_Running: Yes
  7. # 兩個執行緒工作正常
  8.               Replicate_Do_DB:
  9.           Replicate_Ignore_DB:
  10.            Replicate_Do_Table:
  11.        Replicate_Ignore_Table:
  12.       Replicate_Wild_Do_Table:
  13.   Replicate_Wild_Ignore_Table:
  14. #沒設定任何規則
  15.                    Last_Errno: 0
  16.                    Last_Error:
  17.                  Skip_Counter:
  18.           Exec_Master_Log_Pos: 2539 # 無論binlog file 還是 pos,都和MASTER保持一致,也就是說BINLOG的接收和RELAYR LOG的APPLY都很正常,有條不紊工作著
  19.               Relay_Log_Space: 2778
  20.               Until_Condition: None
  21.                Until_Log_File:
  22.                 Until_Log_Pos: 0
  23. ...
  24.         Seconds_Behind_Master: 0
  25. Master_SSL_Verify_Server_Cert: No
  26.                 Last_IO_Errno: 0
  27.                 Last_IO_Error:
  28.                Last_SQL_Errno: 0
  29.                Last_SQL_Error:
  30.   Replicate_Ignore_Server_Ids:
  31. # 沒設定忽略某些 server-id 上的BINLOG
  32.              Master_Server_Id: 123315
  33.                   Master_UUID: 35cc99c6-0297-11e4-9916-782bcb2c9453
  34.              Master_Info_File: /data/db11_3316/master.info 
  35.                     SQL_Delay: 0 # 沒有設定複製延遲策略 
  36.           SQL_Remaining_Delay: NULL
  37.       Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
  38.            Master_Retry_Count: 4294967295
  39.                   Master_Bind:
  40.       Last_IO_Error_Timestamp:
  41.      Last_SQL_Error_Timestamp:
  42.                Master_SSL_Crl:
  43.            Master_SSL_Crlpath:
  44.            Retrieved_Gtid_Set: 35cc99c6-0297-11e4-9916-782bcb2c9453:1-451 
  45.             Executed_Gtid_Set: 35cc99c6-0297-11e4-9916-782bcb2c9453:1-2455:792490-4517929 Auto_Position: 1


從上面的日誌發現什麼了沒?尤其是這兩行點選(此處)摺疊或開啟
  1. Retrieved_Gtid_Set: 35cc99c6-0297-11e4-9916-782bcb2c9453:1-4517929 
  2.  Executed_Gtid_Set: 35cc99c6-0297-11e4-9916-782bcb2c9453:1-2455:792490-4517929 Auto_Position: 1

這下有點明白了吧,意思是
1、SLAVE從MASTER上覆制了GTID範圍是:1-4517929;
2、SLAVE上執行GTID的範圍分為兩段,一段是:1-2455,另一段是:792490-4517929;


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

 情況1

  1. 正常滴,在MySQL 5.6啟用GTID後,部署REPLICATION複製時,可以設定 MASTER_AUTO_POSITION = 1,讓 SLAVE 根據 GTID 自動選擇適當的事務點進行復制,DBA基本上無需關注和擔心主從不一致的問題,還是很讓DBA省心的。 
  2. 在啟用 MASTER_AUTO_POSITION = 1 的情況下,正常是不會發生 GTID 中間有個空隙,產生斷點的問題發生。除非是下面這種情況:
  3. 1、人工暫停SLAVE程式;
  4. 2、MASTER上繼續寫入資料;
  5. 3、MASTER上重新整理LOG;
  6. 4、MASTER上刪除舊BINLOG,只保留最新的BINLOG;
  7. 5、SLAVE上啟動MASTER,這時候會報錯,像下面這樣:
  8. Last_IO_Errno: 1236
  9. 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.'

  10. 針對這種問題的處理方法可以這麼做:
  11. 1、關閉MASTER_AUTO_POSITION,即設定 MASTER_AUTO_POSITION = 0;
  12. 2、手工CHANGE BINLOG FILE & POS;
  13. 這種情況下,不能再次設定 MASTER_AUTO_POSITION = 1,否則還會再次報錯。 


  1. 情況2

  1. 1、正常配置 REPLICATION 複製,但是設定 MASTER_AUTO_POSITION = 0,也就是人工指定 BINLOG FILE & POS的傳統方法;
  2. 2、在複製過程中,暫時關閉 SLAVE 程式;
  3. 3、手工修改 BINLOG FILE & POS 資訊,指向新的 BINLOG FILE & POS 點;
  4. 4、啟動SLAVE,這時候就會發現 GTID 斷點的現象重現了;
  5. 在主從高可用模式下,可能主從間會發生切換,然後再次切換回來,這時候也可能發生上述的斷點問題。因此我們建議採用雙主來部署高可用切換,基本上可以實現任意來回切換,無需手工指定新的 BINLOG FIEE & POS 資訊。
  6. 還有最後一種情況,就是在 MASTER 上執行了 RESET MASTER,導致 MASTER 上的 BINLOG FILE & POS 全部重置,SLAVE 上讀取到的資訊自然也就不一致了。
  7. 好了,說了那麼多,我們最後來說下如何應對處理 GTID 斷點的問題。

  8. 方法一:手工修改 BINLOG FILE & POS
  9. 1、關閉SLAVE;
  10. 2、手工CHANGE BINLOG FILE & POS,指向MASTER上最新產生的BINLOG FILE & POS,並且設定 MASTER_AUTO_POSITION = 0;
  11. 3、啟動SLAVE;

  1. 方法二:手工修改 GTID_PURGED 值
  2. 1、關閉 SLAVE;
  3. 2、在 SLAVE 上執行 RESET MASTER,重設 SLAVE 上的 BINLOG FILE & POS(如果這個節點用於複製中繼,要注意所有binlog是否都被讀取完畢,避免資料丟失);
  4. 3、在 SLAVE 上執行 SET @@GLOBAL.GTID_PURGED = '35cc99c6-0297-11e4-9916-782bcb2c9453:1-2455';
  5. 4、啟動 SLAVE;
  6. 這種做法比較費解一點,意思是,我們告訴SLAVE要主動拋棄掉 MASTER 上傳輸過來的某些區間的事務。在這個例子中,我們拋棄了 1-2455 這個區間,也就是在 GTID 從 2466 開始,又會繼續應用 RELAY LOG 了,相比我們最開始的那個資訊:

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

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

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


原文:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29096438/viewspace-2054962/,如需轉載,請註明出處,否則將追究法律責任。

相關文章