MySQL 5.6版本GTID復(fù)制異常處理一例

2018-07-31 19:00 更新

昨天處理了一個(gè)MySQL 5.6版本下開啟GTID模式復(fù)制異常案例,MASTER上的任何操作都無(wú)法在SLAVE上應(yīng)用,SLAVE的RELAY LOG里有記錄,但SLAVE的BINLOG卻找不到蛛絲馬跡。由于開啟了GTID,所以排查起來(lái)也簡(jiǎn)單,只需要在SLAVE上把RELAY LOG和BINLOG分別解析成文本文件,再直接搜索MASTER的UUID,就能找到SLAVE上是否應(yīng)用了MASTER復(fù)制過(guò)來(lái)的事務(wù)。 排查過(guò)程中,曾經(jīng)一度懷疑是因?yàn)樵O(shè)置了BINLOG-DO或者IGNORE規(guī)則,或者設(shè)置了REPLICATION-DO或IGNORE規(guī)則,甚至是GTID的嚴(yán)重BUG,但都沒(méi)發(fā)現(xiàn)端倪。直到從 SHOW SLAVE STATUS 里發(fā)現(xiàn)下面這個(gè)信息:

[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
# 兩個(gè)線程工作正常
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
#沒(méi)設(shè)置任何規(guī)則
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
 Exec_Master_Log_Pos: 2539 # 無(wú)論binlog file 還是 pos,都和MASTER保持一致,也就是說(shuō)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:
# 沒(méi)設(shè)置忽略某些 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 # 沒(méi)有設(shè)置復(fù)制延遲策略          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

從上面的日志發(fā)現(xiàn)什么了沒(méi)?尤其是這兩行:

           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

這下有點(diǎn)明白了吧,意思是:

1、SLAVE從MASTER上復(fù)制了GTID范圍是:1-451;
2、SLAVE上執(zhí)行GTID的范圍分為兩段,一段是:1-2455,另一段是:792490-4517929;

尼瑪,不應(yīng)該是連續(xù)的嘛,怎么會(huì)這么奇葩⊙﹏⊙b,這可如何是好呀,好捉急~~~ 莫急,且容我們慢慢分析為啥GTID從MASTER到SLAVE之后發(fā)生了斷點(diǎn),產(chǎn)生了間隙。

正常滴,在MySQL 5.6啟用GTID后,部署REPLICATION復(fù)制時(shí),可以設(shè)定 MASTER_AUTO_POSITION = 1,讓 SLAVE 根據(jù) GTID 自動(dòng)選擇適當(dāng)?shù)氖聞?wù)點(diǎn)進(jìn)行復(fù)制,DBA基本上無(wú)需關(guān)注和擔(dān)心主從不一致的問(wèn)題,還是很讓DBA省心的。 在啟用 MASTER_AUTO_POSITION = 1 的情況下,正常是不會(huì)發(fā)生 GTID 中間有個(gè)空隙,產(chǎn)生斷點(diǎn)的問(wèn)題發(fā)生。除非是下面這種情況:

1、人工暫停SLAVE進(jìn)程;
2、MASTER上繼續(xù)寫入數(shù)據(jù);
3、MASTER上刷新LOG;
4、MASTER上刪除舊BINLOG,只保留最新的BINLOG;
5、SLAVE上啟動(dòng)MASTER,這時(shí)候會(huì)報(bào)錯(cuò),像下面這樣:
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.'

針對(duì)這種問(wèn)題的處理方法可以這么做:

1、關(guān)閉MASTER_AUTO_POSITION,即設(shè)置 MASTER_AUTO_POSITION = 0;
2、手工CHANGE BINLOG FILE & POS;

這種情況下,不能再次設(shè)置 MASTER_AUTO_POSITION = 1,否則還會(huì)再次報(bào)錯(cuò)。 還有一種情況會(huì)發(fā)生 GTID 間隙斷點(diǎn)問(wèn)題,例如這樣:

1、正常配置 REPLICATION 復(fù)制,但是設(shè)置 MASTER_AUTO_POSITION = 0,也就是人工指定 BINLOG FILE & POS的傳統(tǒng)方法;
2、在復(fù)制過(guò)程中,暫時(shí)關(guān)閉 SLAVE 進(jìn)程;
3、手工修改 BINLOG FILE & POS 信息,指向新的 BINLOG FILE & POS 點(diǎn);
4、啟動(dòng)SLAVE,這時(shí)候就會(huì)發(fā)現(xiàn) GTID 斷點(diǎn)的現(xiàn)象重現(xiàn)了;

在主從高可用模式下,可能主從間會(huì)發(fā)生切換,然后再次切換回來(lái),這時(shí)候也可能發(fā)生上述的斷點(diǎn)問(wèn)題。因此我們建議采用雙主來(lái)部署高可用切換,基本上可以實(shí)現(xiàn)任意來(lái)回切換,無(wú)需手工指定新的 BINLOG FIEE & POS 信息。

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

好了,說(shuō)了那么多,我們最后來(lái)說(shuō)下如何應(yīng)對(duì)處理 GTID 斷點(diǎn)的問(wèn)題。

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

1、關(guān)閉SLAVE;
2、手工CHANGE BINLOG FILE & POS,指向MASTER上最新產(chǎn)生的BINLOG FILE & POS,并且設(shè)置 MASTER_AUTO_POSITION = 0;
3、啟動(dòng)SLAVE;

方法二:手工修改 GTID_PURGED 值

1、關(guān)閉 SLAVE;
2、在 SLAVE 上執(zhí)行 RESET MASTER,重設(shè) SLAVE 上的 BINLOG FILE & POS(如果這個(gè)節(jié)點(diǎn)用于復(fù)制中繼,要注意所有binlog是否都被讀取完畢,避免數(shù)據(jù)丟失);
3、在 SLAVE 上執(zhí)行 SET @@GLOBAL.GTID_PURGED = '35cc99c6-0297-11e4-9916-782bcb2c9453:1-2455';
4、啟動(dòng) SLAVE;

這種做法比較費(fèi)解一點(diǎn),意思是,我們告訴SLAVE要主動(dòng)拋棄掉 MASTER 上傳輸過(guò)來(lái)的某些區(qū)間的事務(wù)。在這個(gè)例子中,我們拋棄了 1-2455 這個(gè)區(qū)間,也就是在 GTID 從 2466 開始,又會(huì)繼續(xù)應(yīng)用 RELAY LOG 了,相比我們最開始的那個(gè)信息:

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

我們強(qiáng)制 SLAVE 只忽略 1-2455 這個(gè)區(qū)間,從 2466 開始繼續(xù)復(fù)制,消除了本來(lái)也會(huì)被忽略的區(qū)間: 792490-4517929,確保新產(chǎn)生的事務(wù)都會(huì)被繼續(xù)應(yīng)用。這個(gè)做法可以參考MySQL手冊(cè):Excluding transactions with gtid_purged。

還有另外一種費(fèi)力不討好的做法,就是在 MASTER 上執(zhí)行一些沒(méi)用的空事務(wù),使得 GTID 的序號(hào)一直在加大,直到超過(guò) 2555 為止,然后在 792490-4517929 這個(gè)區(qū)間依法炮制一番,但我們非常不推薦采用這種做法,既麻煩又容易誤操作。 說(shuō)了這么多,在 MySQL 5.6及以上版本中,我們強(qiáng)烈建議啟用 MASTER_AUTO_POSITION = 1,讓 MySQL 自己去做判斷,減少一些不必要的問(wèn)題,并且采用雙主(其中一個(gè)主設(shè)為只讀)的方式,方便兩個(gè)主之間可以隨意相互切換,而不必?fù)?dān)心數(shù)據(jù)不一致。

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

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)