mysql slave lock 跳过_处理 MySQL 因为 SLAVE 崩溃导致需要手动跳过 GTID 的问题 | 关于 GTID...
今天發(fā)生了與之前某篇博客相似的問題,有同學在不同步的 binlog 庫中使用語句 database.table 命令對表進行 drop 導致 master 丟棄該表但是從庫并未能同步到該操作。并且后續(xù)又實用 use xxxx 對該表進行增刪字段,由于salve 并未建立此表于是 slave 崩潰的情況。
slave 崩潰信息通過查看 MySQL 錯誤日志差不多是這樣
2019-07-11 15:05:12 17674 [ERROR] Slave SQL: Error 'Table'api.ring_king_record'doesn't exist'on query. Default database:'api'. Query:'ALTER TABLE `api`.`ring_king_record`
CHANGE COLUMN `course_id` `course_id` VARCHAR(45) NULL DEFAULT ''AFTER `id`,
CHANGE COLUMN `title` `title` VARCHAR(45) NULL DEFAULT ''AFTER `course_id`,
CHANGE COLUMN `serialNumber` `serial_number` VARCHAR(45) CHARACTER SET 'latin1' NULL DEFAULT '' COMMENT '唯一標示碼',
CHANGE COLUMN `tsaCount` `tsa_count` VARCHAR(45) CHARACTER SET 'latin1' NULL DEFAULT '' COMMENT '剩余確權次數(shù)'', Error_code: 1146
2019-07-11 15:05:12 17674 [Warning] Slave: Table 'api.ring_king_record' doesn't exist Error_code: 1146
2019-07-11 15:05:12 17674 [ERROR] Error running query, slave SQL thread aborted. Fix the problem, and restart the slave SQL thread with "SLAVE START". We stopped at log 'mysql-bin.000762' position 16412436.2019-07-11 15:05:12 17674 [Note] Slave I/O thread: connected to master 'xxxx',replication started in log 'mysql-bin.000763' at position 2157463
可以很清晰的看到錯誤的原因是 api.ring_king_record 這個表根本不存在,但是卻嘗試去操作 change column 的操作。所以 slave 直接崩潰了, MySQL 提示我們數(shù)據(jù)庫已經停止同步希望我們修復了這個問題之后再使用 SLAVE START 來啟動 slave 的同步跟上 master.
這里只需要關注兩個地方
1. mysql-bin.000762 可以讓我們定位到發(fā)生問題是哪個 binlog。
2. position 可以讓我們定位到發(fā)生的位置是在哪兒。
通過 position 16412435 如果你可以訪問 master 物理機,那么可以通過訪問 binlog 所在目錄使用命令
mysqlbinlog mysql-bin.000672 | grep -C 100 16412435
去查看相關的信息,包括前后是什么語句,之類的。
如果類似于使用了 rds 這樣的 MySQL 服務,可以去 master 所在的 rds 并使用 MySQL Client 上執(zhí)行語句
show binlog events in 'mysql-bin.000762' from 16412436 limit 10\G;
我們可以得到從崩潰該語句開始的一些信息
mysql> show binlog events in 'mysql-bin.000762' from 16412436 limit 10\G;*************************** 1. row ***************************Log_name: mysql-bin.000762Pos:16412436Event_type: Gtid
Server_id:1215612563End_log_pos:16412484Info: SET @@SESSION.GTID_NEXT= '8dcfd361-10cb-11e9-9060-506b4b2ac23e:30038123'
*************************** 2. row ***************************Log_name: mysql-bin.000762Pos:16412484Event_type: Query
Server_id:1215612563End_log_pos:16412989Info: use `api`; ALTER TABLE `api`.`ring_king_record`
CHANGE COLUMN `course_id` `course_id` VARCHAR(45) NULL DEFAULT ''AFTER `id`,
CHANGE COLUMN `title` `title` VARCHAR(45) NULL DEFAULT ''AFTER `course_id`,
CHANGE COLUMN `serialNumber` `serial_number` VARCHAR(45) CHARACTER SET 'latin1' NULL DEFAULT '' COMMENT '唯一標示碼',
CHANGE COLUMN `tsaCount` `tsa_count` VARCHAR(45) CHARACTER SET 'latin1' NULL DEFAULT '' COMMENT '剩余確權次數(shù)'
*************************** 3. row ***************************Log_name: mysql-bin.000762Pos:16412989Event_type: Gtid
Server_id:1215612563End_log_pos:16413037Info: SET @@SESSION.GTID_NEXT= '8dcfd361-10cb-11e9-9060-506b4b2ac23e:30038124'
*************************** 4. row ***************************Log_name: mysql-bin.000762Pos:16413037Event_type: Query
Server_id:1215612563End_log_pos:16413277Info:/*rds internal mark*/CREATE TABLE IF NOT EXISTS mysql.ha_health_check (
id BIGINT DEFAULT0,
type CHAR(1) DEFAULT '0',
PRIMARY KEY (type)
這里可以很清楚的看到崩潰位置?16412436 GTID:?8dcfd361-10cb-11e9-9060-506b4b2ac23e:30038123 執(zhí)行了 change column 的操作導致了崩潰。
現(xiàn)在我們要恢復 slave 就需要跳過這個報錯的語句。因為全局開啟了 GTID 的關系我們無法使用傳統(tǒng)的
root@(none) >stop slave;
Query OK,0 rows affected (0.00sec)
root@(none)>SET GLOBAL SQL_SLAVE_SKIP_COUNTER =N; #跳過N個事務
Query OK,0 rows affected (0.00sec)
root@(none)>start slave;
Query OK,0 rows affected, 1 warning (0.03sec)
來恢復 會報錯
ERROR1858 (HY000): sql_slave_skip_counter can not be set when the server is running with @@GLOBAL.GTID_MODE = ON. Instead, for each transaction that you want to skip, generate an empty transaction with the same GTID as the transaction
我在網(wǎng)上查了不少資料,但是感覺大部分都是互相 copy xjb 扯淡,也根本使用不了。
下面是我結合幾個靠譜博客和官方文檔寫的一個配置
stop slave;
reset master;
reset slave;
CHANGE MASTER TO MASTER_HOST='master_address',MASTER_USER='xxx', MASTER_PASSWORD='xxx';set global gtid_purged = '8dcfd361-10cb-11e9-9060-506b4b2ac23e:30038123';
SET @@SESSION.GTID_NEXT= '8dcfd361-10cb-11e9-9060-506b4b2ac23e:30038124';
begin;
commit;
SET GTID_NEXT="AUTOMATIC";
start slave;
下面我會依次介紹這些命令是用來干嘛的。
首先我們所有現(xiàn)在針對去恢復的 slave 操作都需要先停止 slave.
reset master 這一步我不是很確定是否真的可以不做,reset master 會將 slave 機器的所有 binlog 都清空。比如之前我們可能是 mysql-bin.000023 這樣子,如果使用了 reset master 會重新從 mysql-bin.000001 開始記錄 binlog。我因為清理了也沒關系,因為我會要顯示的指定我從 master 機器的什么位置開始消費并且追上 master 所以就設置了。
reset slave 將讓 slave 忘記主從復制的關系的位置信息,它會刪除 master.info 和 relay-log.iinfo 文件重置 relaylog 信息。我們知道 relay-log 其實就是用于記錄 slave 復制 master 信息復制到哪里來了這里會重置這些信息。
然后我哦們指定 change master 重新指定我們要跟隨的 master 地址。
設置全局的 gtid_purged 這里注意 這個 gtid_purged 用于告訴你的 slave 無視哪些 gtid 的記錄段,就是我們會無視掉所有之前我們消費過的記錄段直到到達我們報錯的位置。這個可以跟下面的參數(shù)聯(lián)動。從上面的圖我們看到我們只需要跳過 change column 那條語句所在的 GTID 重新從
8dcfd361-10cb-11e9-9060-506b4b2ac23e:30038124
開始消費即可跳過,所以上面我們使用 30038124-1 來表示我們需要 purged 的部分。
最后我們通過提交一個空事務并指定自動位移 GTID 來恢復我們的 slave。
一切完成之后我們啟動 slave 使用 start slave
這個時候我們的 slave 從庫會從我們指定的位置開始追上 master 只需要等待一段時間即可,那么如何判斷已經追上了 master 呢?
我們在從庫上執(zhí)行
show slave status
mysql>show slave status\G;*************************** 1. row ***************************Slave_IO_State: Waitingfor master to send eventMaster_Host: xxxxxxxxxxxxMaster_User: xxxx
Master_Port:3306Connect_Retry:60Master_Log_File: mysql-bin.000764Read_Master_Log_Pos:6362259Relay_Log_File: mysqld-relay-bin.000006Relay_Log_Pos:6362469Relay_Master_Log_File: mysql-bin.000764Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB: xxxxxxxxxxxx
Replicate_Ignore_DB: mysql
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno:0Last_Error:
Skip_Counter:0Exec_Master_Log_Pos:6362259Relay_Log_Space:6362761Until_Condition: None
Until_Log_File:
Until_Log_Pos:0Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master:0Master_SSL_Verify_Server_Cert: No
Last_IO_Errno:0Last_IO_Error:
Last_SQL_Errno:0Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id:1215612563Master_UUID: 8dcfd361-10cb-11e9-9060-506b4b2ac23e
Master_Info_File:/var/lib/mysql/master.info
SQL_Delay:0SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waitingfor the slave I/O thread to update it
Master_Retry_Count:86400Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set: 8dcfd361-10cb-11e9-9060-506b4b2ac23e:30038448-30142673Executed_Gtid_Set: 0cf0e744-f9f6-11e8-bb7a-00163e302177:1-27887,
8dcfd361-10cb-11e9-9060-506b4b2ac23e:1-30142673Auto_Position:1
比較?Read_Master_Log_Pos 和 Exec_Master_Log_Pos 差不多就說明已經追上了 master。
Relay_Log_Pos 和他們差不多能說明 io 線程也能拉到最新的數(shù)據(jù)。
當我們有錯誤的時候 show slave status 也可以給我們提供非常多的信息,例如最后出錯的信息是啥。為什么報錯都有顯示,如果沒有第一時間去看錯誤日志,使用命令在這里看錯誤信息也不錯。
另外使用?show variables like '%gtid%'; 也可以給我們提供一些基于 gtid 的信息。
唔。。。又是修數(shù)據(jù)跑監(jiān)控的一天=。=
---------------------------------分割線---------------------------------
關于 GTID 昨晚回去 我重新翻看了一些資料覺得還是有必要多說兩句。
可以說 GTID 的出現(xiàn)解決了之前完全依賴 master 文件和 pos 的來切換主從的問題得到了解決。
MySQL 版本5.6 引入了 GTID 解決主從同步位點問題。GTID 的全稱是 Global Transaction Identifier 也就是全局事務 ID,是一個事務在提交的時候生成的,是這個事務的唯一標識。它由兩部分組成:
GTID=server_uuid:gno
其中 server_uuid 是一個實例第一次啟動時自動生成的,可以通過我們上面介紹的命令 show master/slave status 看到該機器的 UUID
gno 是一個整數(shù),初始化是1,每次提交事務的時候分配給這個事務,并加 1。
GTIO 模式的啟動配置:
#GTID
gtid_mode=on
enforce_gtid_consistency=on
log-slave-updates=1
GTID_mode 開啟的參數(shù)相關的是前兩個參數(shù), log-slave-updates = 1 是開啟連貫復制 log
本身 slave 同步 master 的日志是不會再放入自己的 binlog 中的,如果我們還有機器在監(jiān)聽 slave 的 binlog 日志就需要開啟?log-slave-updates 參數(shù)。
在 GTID 模式下,每個事務都會跟一個 GTID 一一對應。這個 GTID 有兩種生成方式,而使用哪種取決于 session 變量 gtid_next 的值。
可以看到上面我們在跳過事務的時候是直接指定了一個 GTID_NEXT 的位置從這個位置開始。
然后指定下面的偏移規(guī)則是 gtid_next=automatic 使用默認值每執(zhí)行一個事務就 +1
這樣每個 MySQL 實例都維護了一個 GTID 集合,用來對應“這個實例執(zhí)行過的所有事務”。
因為這個集合的存在,所以我們在重制 ?slave 和 master 的進度的時候,如果 slave 并沒有通過?gtid_purged 或者通過指定 GTID_NEXT 跳過已經執(zhí)行的事務 slave 會嘗試去執(zhí)行這些事務,并且因為主鍵沖突等原因報錯崩潰。
所以現(xiàn)在回頭過來看這幾條命令
set gtid_next='aaaaaaaa-cccc-dddd-eeee-ffffffffffff:10';
begin;
commit;set gtid_next=automatic;
start slave;
其實它的意義是 首先 :10 這個gtid 是有問題那個 GTID 就是執(zhí)行了會崩潰的那個 GTID 。
然后這個時候我們對其替換成一個空事務。
再設置之后都正常加一偏移數(shù)據(jù)。
最后啟動 slave 。這樣的話當我們的 slave 運行到這里的時候會因為已經因為這個 GTID 執(zhí)行了空事務,而無視跳過 master 傳遞過來的有問題的 binlog 從而達到跳過有問題事務的目的。
由于沒有實操過主備切換,這里注意到資料大部分都提到 GTID 模式下只需要指定 change master to 新的機器即可。新的 master 會自動計算相關的位點。
CHANGE MASTER TO MASTER_HOST='xxxx',MASTER_USER='xxx', MASTER_PASSWORD='xxx';
master_auto_position=1
Reference:
https://yq.aliyun.com/articles/155827 ?MySQL GTID 主從復制錯誤修復方法
https://www.douban.com/note/446551760/RESET MASTER 和RESET SLAVE 命令的使用方法 注意事項
https://www.cnblogs.com/zhoujinyi/p/4717951.html ?MySQL5.6 新特性之GTID
總結
以上是生活随笔為你收集整理的mysql slave lock 跳过_处理 MySQL 因为 SLAVE 崩溃导致需要手动跳过 GTID 的问题 | 关于 GTID...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql删除了密码怎样恢复_windo
- 下一篇: mysql8.0client_navic