作者:盧文雙 資深數(shù)據(jù)庫研發(fā)工程師 目前負責青云云數(shù)據(jù)庫的研發(fā)工作震捣,熱衷于研究主流數(shù)據(jù)庫架構(gòu)、源碼绿满,對關(guān)系型數(shù)據(jù)庫 MySQL/PostgreSQL 及分布式數(shù)據(jù)庫有深入研究乌妒。
前言
在為 Xenon[1] 適配新版 Percona XtraBackup 8.0[2](原有代碼適配于 2.4 版本)時遇到的一些問題,在定位過程中對比了 XtraBackup 2.4 和 8.0 的異同蟀苛。
版本信息[3]:
- Percona-Server 8.0.19-10
- Percona-Xtrabackup 8.0.13
問題描述
問題 1
MySQL 8.0 + Semi-Sync + 持續(xù)寫入數(shù)據(jù)期間執(zhí)行重建后, change master to && start slave
報錯:
Last_Error: Could not execute Write_rows event on table db1.t1; Duplicate entry '28646' for key 't1.PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000052, end_log_pos 437
問題 2
MySQL 8.0 + Group Replication + 持續(xù)寫入數(shù)據(jù)期間執(zhí)行重建后逮诲,change master to && start group_replication
報錯:
2020-08-21T14:51:09.977606+08:00 61 [System] [MY-010597] [Repl] 'CHANGE MASTER TO FOR CHANNEL 'group_replication_applier' executed'. Previous state master_host='<NULL>', master_port= 0, master_log_file='', master_log_pos= 4, master_bind=''. New state master_host='<NULL>', master_port= 0, master_log_file='', master_log_pos= 4, master_bind=''.
2020-08-21T14:51:09.987494+08:00 61 [ERROR] [MY-013124] [Repl] Slave SQL for channel 'group_replication_applier': Slave failed to initialize relay log info structure from the repository, Error_code: MY-013124
2020-08-21T14:51:09.987542+08:00 61 [ERROR] [MY-011534] [Repl] Plugin group_replication reported: 'Error while starting the group replication applier thread'
2020-08-21T14:51:09.987651+08:00 7 [ERROR] [MY-011669] [Repl] Plugin group_replication reported: 'Unable to initialize the Group Replication applier module.'
2020-08-21T14:51:09.987831+08:00 7 [ERROR] [MY-011735] [Repl] Plugin group_replication reported: '[GCS] The member is leaving a group without being on one.'
要解釋這兩個問題帜平,首先要弄清楚 XtraBackup 2.4 和 8.0 的區(qū)別。
XtraBackup 2.4/8.0 版本區(qū)別
通過查到可知 XtraBackup 2.4 與 8.0 版本備份記錄信息有如下不同點:
- 2.4 備份生成的 xtrabackup_binlog_info 文件記錄的 GTID 信息是準確的梅鹦,但是備份恢復后
show master status
顯示的 GTID 是不準確的裆甩; - 8.0 備份的實例中只有 InnoDB 表時,xtrabackup_binlog_info 文件記錄的 GTID 信息不一定是準確的齐唆,但是備份恢復后
show master status
顯示的 GTID 是準確的淑掌; - 8.0 備份的實例中有非 InnoDB 表時,xtrabackup_binlog_info 文件記錄的 GTID 信息是準確的蝶念,備份恢復后
show master status
顯示的 GTID 也是準確的抛腕。
兩個版本執(zhí)行過程如下:
2.4 | 8.0 |
---|---|
1. start backup 2. copy ibdata1 / copy .ibd file 3. excuted FTWRL 4. backup non-InnoDB tables and files 5. writing xtrabackup_binlog_info 6. executed FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS 7. executed UNLOCK TABLES 8. copying ib_buffer_pool 9. completed OK! |
1. start backup 2. copy .ibd file 3. backup non-InnoDB tables and files 4. executed FLUSH NO_WRITE_TO_BINLOG BINARY LOGS 5. selecting LSN and binary log position from p_s.log_status 6. copy last binlog file 7. writing /mysql/backup/backup/binlog.index 8. writing xtrabackup_binlog_info 9. executing FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS 10. copy ib_buffer_pool 11. completed OK! |
注意:當存在非 InnoDB 表時,8.0 會執(zhí)行 FTWRL媒殉。
通過兩個版本執(zhí)行過程命令不難看出担敌,主要區(qū)別在于 8.0 版本當只存在 InnoDB 表時,執(zhí)行步驟 5 命令來獲取 LSN廷蓉、binlog position全封、GTID。
手冊中[4]桃犬,對于表 log_status 的描述如下:
The log_status table provides information that enables an online backup tool to copy the required log files without locking those resources for the duration of the copy process.
When the log_status table is queried, the server blocks logging and related administrative changes for just long enough to populate the table, then releases the resources. The log_status table informs the online backup which point it should copy up to in the source's binary log and gtid_executed record, and the relay log for each replication channel. It also provides relevant information for individual storage engines, such as the last log sequence number (LSN) and the LSN of the last checkpoint taken for the InnoDB storage engine.
從上述手冊描述可知刹悴,performance_schema.log_status
是 MySQL 8.0 提供給在線備份工具獲取復制信息的表格,查詢該表時攒暇,mysql server 將阻止日志的記錄和相關(guān)的更改來獲取足夠的時間以填充該表土匀,然后釋放資源。
log_status 表通知在線備份工具當前主庫的 binlog 的位點和 gtid_executed 的值以及每個復制通道的 relay log形用。另外就轧,它還提供了各個存儲引擎的相關(guān)信息,比如田度,提供了 InnoDB 引擎使用的最后一個日志序列號(LSN)和最后一個檢查點的 LSN妒御。
表 log_status 定義參數(shù)信息示例如下:
-- Semi-Sync
mysql> select * from performance_schema.log_status\G
*************************** 1. row ***************************
SERVER_UUID: 6b437e80-e5d5-11ea-88e3-52549922fdbb
LOCAL: {"gtid_executed": "6b437e80-e5d5-11ea-88e3-52549922fdbb:1-201094", "binary_log_file": "mysql-bin.000079", "binary_log_position": 195}
REPLICATION: {"channels": []}
STORAGE_ENGINES: {"InnoDB": {"LSN": 23711425885, "LSN_checkpoint": 23711425885}}
1 row in set (0.00 sec)
-- Group Replication
mysql> select * from performance_schema.log_status\G
*************************** 1. row ***************************
SERVER_UUID: 7bd32480-e5d5-11ea-8f8a-525499cfbb7d
LOCAL: {"gtid_executed": "aaaaaaaa-aaaa-aaaa-aaaa-53ab6ea1210a:1-11", "binary_log_file": "mysql-bin.000003", "binary_log_position": 1274}
REPLICATION: {"channels": [{"channel_name": "group_replication_applier", "relay_log_file": "mysql-relay-bin-group_replication_applier.000004", "relay_log_position": 311, "relay_master_log_file": "", "exec_master_log_position": 0}, {"channel_name": "group_replication_recovery", "relay_log_file": "mysql-relay-bin-group_replication_recovery.000003", "relay_log_position": 151, "relay_master_log_file": "", "exec_master_log_position": 0}]}
STORAGE_ENGINES: {"InnoDB": {"LSN": 20257208, "LSN_checkpoint": 20257208}}
1 row in set (0.00 sec)
問題定位
問題 1:MySQL 8.0 + Semi-Sync 重建
Xenon 原有的重建邏輯適配于 MySQL 5.6/5.7(重建過程中 Xenon 進程存活),一直無問題镇饺。
Xenon 重建邏輯
- 禁用 raft乎莉,將 Xenon 狀態(tài)設為 LEARNER;
- 如 mysql 進程存在奸笤,則
stop mysql
惋啃; - 清空 MySQL 數(shù)據(jù)目錄;
- 執(zhí)行
xtrabackup --backup
以 xbstream 方式獲取對端數(shù)據(jù)揭保; - 執(zhí)行
xtrabackup --prepare
應用 redo log肥橙; - 啟動 mysql;
- 執(zhí)行
stop slave; reset slave all
秸侣; - 執(zhí)行
reset master
存筏,以 xtrabackup_binlog_info 文件中的 GTID 為準設置 gtid_purged; - 啟用 raft味榛,將 Xenon 狀態(tài)設為 FOLLOWER 或 IDLE椭坚;
- 等待 Xenon 自動
change master to
到主節(jié)點; - 執(zhí)行
start slave
搏色。
Duplicate entry '28646' for key 't1.PRIMARY'
表示主鍵沖突善茎,說明表中已存在相同主鍵的行。跟蹤重建過程中的 general log频轿,發(fā)現(xiàn)在第 6 和第 7 步中間垂涯,也就是設置 gtid_purged 之前憑空多出了 change master to
和 start slave
操作烁焙。
grneral log(部分)
通過下面示例代碼信息可看出,在設置 gtid_purged 之前已經(jīng)啟用復制獲取了一部分數(shù)據(jù)耕赘,那么 xtrabackup_binlog_info 中的內(nèi)容就不再準確骄蝇,之后設置的 GTID 與實際數(shù)據(jù)就不一致,實際的數(shù)據(jù)比設置的 GTID 要多操骡,會引起主鍵沖突九火。
SET GLOBAL rpl_semi_sync_master_enabled=OFF
SET GLOBAL read_only = 1
SET GLOBAL super_read_only = 1
START SLAVE
STOP SLAVE
CHANGE MASTER TO MASTER_HOST = '192.168.0.3', MASTER_USER = 'qc_repl', MASTER_PASSWORD = <secret>, MASTER_PORT = 3306, MASTER_AUTO_POSITION = 1
START SLAVE
BEGIN
COMMIT /* implicit, from Xid_log_event */
......
BEGIN
COMMIT /* implicit, from Xid_log_event */
SET GLOBAL rpl_semi_sync_master_enabled=OFF
SET GLOBAL read_only = 1
SET GLOBAL super_read_only = 1
START SLAVE
BEGIN
COMMIT /* implicit, from Xid_log_event */
......
BEGIN
COMMIT /* implicit, from Xid_log_event */
STOP SLAVE
RESET SLAVE ALL
RESET MASTER
SET GLOBAL gtid_purged='6b437e80-e5d5-11ea-88e3-52549922fdbb:1-102610
'
START SLAVE
SET GLOBAL read_only = 1
SET GLOBAL super_read_only = 1
SET GLOBAL sync_binlog=1000
SET GLOBAL innodb_flush_log_at_trx_commit=1
SHOW SLAVE STATUS
SHOW MASTER STATUS
SET GLOBAL rpl_semi_sync_master_enabled=OFF
SET GLOBAL read_only = 1
SET GLOBAL super_read_only = 1
START SLAVE
SHOW SLAVE STATUS
SHOW MASTER STATUS
STOP SLAVE
CHANGE MASTER TO MASTER_HOST = '192.168.0.3', MASTER_USER = 'qc_repl', MASTER_PASSWORD = <secret>, MASTER_PORT = 3306, MASTER_AUTO_POSITION = 1
START SLAVE
疑問 1
問:為什么之前 MySQL 5.6/5.7 從沒遇到過這個問題呢?
答:多次測試發(fā)現(xiàn)在 MySQL 5.6/5.7 中 set gtid_purged
前執(zhí)行 change master to & start slave
會報復制錯誤 Slave failed to initialize relay log info structure from the repository
册招,在 reset slave all; reset master岔激、set gtid_purged
后再執(zhí)行 change master to & start slave
就可以正常復制,數(shù)據(jù)無誤是掰。
疑問 2
問:Xenon 中哪塊邏輯引起的額外的 change master to
和 start slave
虑鼎?
答:在重建期間 Xenon 會設為 LEARNER 角色,而該角色在探測到 MySQL Alive后冀惭,會 change master
到主節(jié)點震叙。
解決方案:
去掉 LEARNER 對 MySQL 的監(jiān)聽,要等 raft 狀態(tài)變?yōu)?FOLLOWER 后散休,由 FOLLOWER 的監(jiān)聽線程
change master to
到主節(jié)點媒楼。[5]對于 MySQL 8.0,重建后無需執(zhí)行 reset master & set gtid_purged 操作戚丸。[6]
問題 2:MySQL 8.0 + Group-Replication 重建后無法啟動 MGR
根據(jù)報錯信息 Slave failed to initialize relay log info structure from the repository
看划址,應該是 XtraBackup 重建后的數(shù)據(jù)目錄保留了 slave 復制信息導致的。
解決方案:
在啟動組復制前執(zhí)行 reset slave
或 reset slave all
即可解決限府。
XtraBackup 8.0 避坑總結(jié)
- 使用 Xtrabackup 8.0 重建集群節(jié)點后夺颤,無需執(zhí)行
reset master
&set gtid_purged
操作; - 使用 Xtrabackup 8.0 重建 Group-Replication 集群節(jié)點后胁勺,啟動組復制前要先執(zhí)行
reset slave
或reset slave all
清除 slave 信息世澜,否則start group_replication
會失敗。
備注參考
[1]. Xenon : https://github.com/radondb/xenon
[2]. Percona XtraBackup : https://www.percona.com/software/mysql-database/percona-xtrabackup
[3]. 版本名含義參考:https://www.percona.com/blog/2020/08/18/aligning-percona-xtrabackup-versions-with-percona-server-for-mysql/
[4]. MySQL 官方手冊:https://dev.mysql.com/doc/refman/8.0/en/performance-schema-log-status-table.html
[5]. pr104:https://github.com/radondb/xenon/pull/104
[6]. pr102:https://github.com/radondb/xenon/pull/102
關(guān)于 RadonDB
RadonDB 開源社區(qū)是一個面向云原生署穗、容器化的數(shù)據(jù)庫開源社區(qū)寥裂, 為數(shù)據(jù)庫技術(shù)愛好者提供圍繞主流開源數(shù)據(jù)庫(MySQL、PostgreSQL案疲、Redis封恰、MongoDB、ClickHouse 等)的技術(shù)分享平臺褐啡,并提供企業(yè)級 RadonDB 開源產(chǎn)品及服務诺舔。
目前 RadonDB 開源數(shù)據(jù)庫系列產(chǎn)品已被 光大銀行、浦發(fā)硅谷銀行、哈密銀行低飒、泰康保險许昨、太平保險、安盛保險逸嘀、陽光保險车要、百年人壽、安吉物流崭倘、安暢物流、藍月亮类垫、天財商龍司光、羅克佳華、升哲科技悉患、無錫匯跑體育残家、北京電信、江蘇交通控股售躁、四川航空坞淮、昆明航空、國控生物 等上千家企業(yè)及社區(qū)用戶采用陪捷。
RadonDB 可基于云平臺與 Kubernetes 容器平臺交付回窘,不僅提供覆蓋多場景的數(shù)據(jù)庫產(chǎn)品解決方案,而且提供專業(yè)的集群管理和自動化運維能力市袖,主要功能特性包括:高可用主從切換啡直、數(shù)據(jù)強一致性、讀寫分離苍碟、一鍵安裝部署酒觅、多維指標監(jiān)控&告警、彈性擴容&縮容微峰、橫向自由擴展舷丹、自動備份&恢復、同城多活蜓肆、異地災備 等颜凯。RadonDB 僅需企業(yè)及社區(qū)用戶專注于業(yè)務層邏輯開發(fā),無需關(guān)注集群高可用選型症杏、管理和運維等復雜問題装获,幫助企業(yè)及社區(qū)用戶大幅度提升業(yè)務開發(fā)與價值創(chuàng)新的效率!
GitHub:
微信群: 請搜索添加群助手微信號 radondb
Xenon 在使用 XtraBackup 8.0 重建數(shù)據(jù)過程中遇到的問題及定位分析厉颤。以及 XtraBackup 2.4 與 8.0 版本在執(zhí)行流程上的異同穴豫。