mysql從庫gtid間隙問題

賀子_DBA時代發表於2022-11-21
今天遇到一個關於從庫gtid有間隙的問題
問題1:發現從庫的gtid集合存在間隙,是什麼原因產生的!
一、問題現象,如下所示:
mysql> show slave  status\G
*************************** 1. row ***************************
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table: emp.%
Replicate_Wild_Ignore_Table:
Master_UUID: 192cb19f-1a3e-11ed-a619-005056b6e3a1
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Retrieved_Gtid_Set: 192cb19f-1a3e-11ed-a619-005056b6e3a1:1- 421996  #你設定了只同步個別庫,但是也是全量拉取binlog,所以這裡是連續的!
Executed_Gtid_Set: 192cb19f-1a3e-11ed-a619-005056b6e3a1:1-419859:419861-421996,   #應用的時候可能有間隙!
Auto_Position: 1
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
mysql>
二、問題分析:
主庫執行了:create database  compattarn_yl; 但是從庫設定Replicate_Wild_Do_Table: emp.%,選擇只同步emp庫,所以從庫在應用relay log的時候,沒有應用create database  compattarn_yl,於是選擇跳過,進而產生了一個間隙,原因是你沒有設定庫級別的過濾,如果你設定的是Replicate_Do_DB或者Replicate_Ignore_DB這類庫級別的過濾,這個時候你create database的時候,就不會產生間隙了!
三、問題解決:把間隙設定一個空事務,補進slave的gtid集合中
1、停止slave程式
mysql> STOP SLAVE;  只要停止stop  sql thread即可!
2、設定事務號,事務號從Retrieved_Gtid_Set獲取,前面的所示間隙為: 192cb19f-1a3e-11ed-a619-005056b6e3a1:419860
在session裡設定gtid_next,即跳過這個GTID,
mysql> SET @@SESSION.GTID_NEXT= ' 192cb19f-1a3e-11ed-a619-005056b6e3a1:419860'
3、設定空事物
mysql> BEGIN; COMMIT;
4、恢復事物號
mysql> SET SESSION GTID_NEXT = AUTOMATIC;
5、啟動slave程式
mysql> START SLAVE;
問題2,如果從庫產生了gtid間隙,那麼當你在從庫上reset slave all,從新change的時候,就可能會有問題!
一、問題描述:
因為某個原因從庫應用gtid的時候產生了間隙,那麼當你需要切換master的時候,例如從change master1切換到change master2,這個時候你需要在從庫執行如下操作:
1)stop slave;
2) reset slave  all ;
3)change  master to  master2;
4)start slave;
但是發現報錯:如下所示
mysql> show slave  status\G
*************************** 1. row ***************************
Slave_IO_Running: No
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Seconds_Behind_Master: 0
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.'
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Auto_Position: 1
Replicate_Rewrite_DB:
Channel_Name: master_21115
Master_TLS_Version:
1 row in set (0.00 sec)
二、問題分析:
因為當你第一次change to  ,並且start slave的時候,slave會把他自己的執行過的gtid集合(也就是SET @@GLOBAL.GTID_PURGED的gtid集合 )傳送給master,並和master執行過的gtid集合做對比,然後找到差異的,這時候就會把間隙也當做差異,slave會認為差異的gtid也需要從master拉取對應的binlog, 但是這個binlog已經被master purge了,不存在了,於是就報錯了 the master has purged binary logs containing GTIDs that the slave requires;
注意如果你是正常的stop slave+start slave,那麼這個時候slave不會嘗試去找間隙的gtid,因為他relay log中已經有所有的gtid,所以不需要從新拉一次binlog了,而reset slave all會清空所有的relay log;
三、 解決辦法:去掉從庫間隙,不去master再要這個gtid了
方法1:直接設定一個空事務即可,推薦使用;
1、停止slave程式
mysql> STOP SLAVE;  只要停止stop  sql thread即可!
2、設定事務號,事務號從Retrieved_Gtid_Set獲取,前面的所示間隙為: 192cb19f-1a3e-11ed-a619-005056b6e3a1:419860
在session裡設定gtid_next,即跳過這個GTID,
mysql> SET @@SESSION.GTID_NEXT= ' 192cb19f-1a3e-11ed-a619-005056b6e3a1:419860'
3、設定空事物
mysql> BEGIN; COMMIT;
4、恢復事物號
mysql> SET SESSION GTID_NEXT = AUTOMATIC;
5、啟動slave程式
mysql> START SLAVE;
方法2:
1)stop slave;
2)在從庫檢視當前gtid的集合,發現從庫應用主庫的gtid集合有間隙(gid= 419860),如下所示
show  master  status;
192cb19f-1a3e-11ed-a619-005056b6e3a1:1-419859:419861-421802,
3)reset  master ;
4) 去掉間隙,改成如下所示的樣子,
SET @@GLOBAL.GTID_PURGED=' 192cb19f-1a3e-11ed-a619-005056b6e3a1:1-421802';
5)start slave;
題外話:
1、如果主庫執行了reset master;
那麼從庫需要執行reset slave  all,然後從新change下,否則報錯找不到master的binlog, 因為主庫reset master會清空binlog檔案,並且binlog序號從1開始!所以slave需要reset slave  all
2、如果master包含兩個gtid,一個是實時用的,一個是靜態的或者說是無用的,
如下所示:
MySQL [(none)]> show master  status\G
*************************** 1. row ***************************
File: mysql-bin.002969
Position: 229787697
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set: 09029e35-2fe0-11eb-a5b5-7cd30ae00c02:1-3,     #這個是由於某種原因產生的一個無用的gtid,或者說靜態gtid
712270d9-9864-11eb-8f3f-7cd30ac477f4:1-2478794562  #這個是本例項實時寫入的gtid,每寫一個事務,該gtid就會加1
這個時候,如果你需要搭建從庫,需要保證在slave上設定SET @@GLOBAL.GTID_PURGED=master的兩個gtid,否則slave也會報錯 the master has purged binary logs containing GTIDs that the slave requires, 除非master當前寫的binlog中包含另一個靜態gtid全部事務,換句話說就是隻會在當前寫的binlog檔案中去找是否有slave需要的那個靜態gtid集合,如果有就拉取,如果沒有就報錯;但是如果slave需要找的是實時用的gtid事務,這個事務沒有在當前寫的binlog檔案中,這時候不會報錯,他會去之前的binlog檔案中找到需要的gtid;
3、relay_log_recovery引數
Enables automatic relay log recovery immediately following server startup. The recovery process creates a new relay log file, initializes the SQL thread position to this new relay log, and initializes the I/O thread to the SQL thread position. Reading of the relay log from the master then continues.
現在我們考慮一個問題,假設當從庫意外當機後,同時從庫的relay log也一起損壞了,而主庫的日誌已經傳到了從庫,只是從庫還沒有來得及應用這些日誌,那麼從庫該如何處理?
1) 在從庫中將relay_log_recovery不設定或者設定為off,如果碰到上面的情形,從庫會丟失那些沒有應用的日誌,主從會不一致。
2)在從庫中將relay_log_recovery設定為on,假如果碰到上面的情形,從庫會自動放棄所有未執行的relay log,重新生成一個relay log,並將從庫的io執行緒的position重新指向新的relay log。並將sql執行緒的position退回到跟io執行緒的position保持一致,重新從新的postion開始拉取binlog並開始同步,( 其實就是從crash時應用的binlog點位開始從新再次拉取binlog,然後sql執行緒回退到這個點位)這樣在從庫中事務不會丟失。這個引數建議開啟。


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

相關文章