一、概述
1.1 背景介紹
復(fù)制延遲一上來,很多人先盯Seconds_Behind_Master。這個(gè)指標(biāo)當(dāng)然要看,但它只能告訴你“延遲已經(jīng)發(fā)生了”,不能告訴你是網(wǎng)絡(luò)拉取慢、Relay Log 堆積、SQL 線程執(zhí)行慢、并行復(fù)制沒吃滿,還是下游被長事務(wù)、DDL、熱點(diǎn)表拖住了。
生產(chǎn)環(huán)境更穩(wěn)的排查方式是:先分清 IO 線程和 SQL 線程,再判斷是拉不到、寫不進(jìn)、還是應(yīng)用不過來。如果只是看單個(gè)秒數(shù),最容易把真正的問題藏掉。
1.2 技術(shù)特點(diǎn)
從復(fù)制鏈路拆問題:Source → 網(wǎng)絡(luò) → IO Thread → Relay Log → SQL / Applier Thread。
兼顧新舊版本字段:MySQL 8.0 推薦SHOW REPLICA STATUS,舊環(huán)境仍可能看到Seconds_Behind_Master。
貼近線上治理:不僅說怎么查,也說怎么避免復(fù)制被長事務(wù)拖死。
1.3 適用場景
場景一:業(yè)務(wù)讀流量打到從庫,延遲突然升高導(dǎo)致讀到舊數(shù)據(jù)。
場景二:主庫寫入正常,從庫relay log堆積。
場景三:發(fā)布、DDL、批處理后復(fù)制延遲持續(xù)幾分鐘甚至幾十分鐘。
1.4 環(huán)境要求
| 組件 | 版本要求 | 說明 |
|---|---|---|
| MySQL | 8.0+ 推薦 | 示例以SHOW REPLICA STATUS為主 |
| 復(fù)制模式 | GTID 或傳統(tǒng) binlog 位點(diǎn) | 兩者命令略有差異 |
| 指標(biāo)采集 | mysqld_exporter | 監(jiān)控復(fù)制延遲與線程狀態(tài) |
| 權(quán)限 | 具備復(fù)制和性能視圖查詢權(quán)限 | 需要查performance_schema |
二、詳細(xì)步驟
2.1 準(zhǔn)備工作
2.1.1 系統(tǒng)檢查
SHOWREPLICASTATUSG SHOWPROCESSLIST; SHOWVARIABLESLIKE'server_id'; SHOWVARIABLESLIKE'gtid_mode'; SHOWVARIABLESLIKE'slave_parallel_workers';
先回答:
IO 線程是否正常拉日志
SQL / Applier 線程是否正常執(zhí)行
延遲是持續(xù)增長還是可追平
并行復(fù)制有沒有啟用,是否真的吃滿
2.1.2 安裝依賴
sudo apt update ||true sudo apt install -y mysql-client jq ||true sudo yum install -y mysql jq ||true
2.1.3 第一輪確認(rèn)
SHOWREPLICASTATUSG SELECT*FROMperformance_schema.replication_connection_statusG SELECT*FROMperformance_schema.replication_applier_status_by_workerG
2.2 核心配置
2.2.1 第一步:先區(qū)分“拉取慢”還是“執(zhí)行慢”
核心判斷字段:
Replica_IO_Running/Slave_IO_Running
Replica_SQL_Running/Slave_SQL_Running
Seconds_Behind_Source/Seconds_Behind_Master
Relay_Log_Space
Last_IO_Error、Last_SQL_Error
如果 IO 線程不正常,優(yōu)先查:
SHOWREPLICASTATUSG
如果 SQL 線程正常但追不上,優(yōu)先查:
SELECTWORKER_ID, LAST_APPLIED_TRANSACTION, APPLYING_TRANSACTION, LAST_APPLIED_TRANSACTION_ORIGINAL_COMMIT_TIMESTAMP, LAST_APPLIED_TRANSACTION_END_APPLY_TIMESTAMP FROMperformance_schema.replication_applier_status_by_worker;
2.2.2 第二步:標(biāo)準(zhǔn)配置示例
# 文件路徑:/etc/my.cnf.d/replication.cnf [mysqld] server_id=102 log_bin=mysql-bin binlog_format=ROW gtid_mode=ON enforce_gtid_consistency=ON relay_log_recovery=ON slave_parallel_type=LOGICAL_CLOCK slave_parallel_workers=8 read_only=ON super_read_only=ON
參數(shù)說明:
binlog_format=ROW:復(fù)制一致性更穩(wěn)
relay_log_recovery=ON:異常重啟后更容易恢復(fù) relay log 狀態(tài)
slave_parallel_workers=8:并行復(fù)制要按業(yè)務(wù)寫入模型調(diào),不是越大越好
super_read_only=ON:避免業(yè)務(wù)誤寫從庫
2.2.3 第三步:按三條線下鉆
看復(fù)制狀態(tài):
SHOWREPLICASTATUSG SHOWBINARYLOGSTATUS;
看熱點(diǎn)事務(wù)和鎖:
SHOWPROCESSLIST; SELECT*FROMinformation_schema.innodb_trxG SHOWENGINEINNODBSTATUSG
看延遲是否卡在單個(gè)事務(wù):
SELECTTHREAD_ID, EVENT_NAME, TIMER_WAIT FROMperformance_schema.events_stages_current WHEREEVENT_NAMELIKE'stage/sql/%';
2.3 啟動(dòng)和驗(yàn)證
2.3.1 啟動(dòng)服務(wù)
STOPREPLICA; STARTREPLICA; SHOWREPLICASTATUSG
2.3.2 功能驗(yàn)證
SHOWREPLICASTATUSG SELECT*FROMperformance_schema.replication_connection_statusG SELECT*FROMperformance_schema.replication_applier_status_by_workerG
三、示例代碼和配置
3.1 完整配置示例
3.1.1 主配置文件
# 文件路徑:/etc/my.cnf.d/replication.cnf [mysqld] server_id=102 log_bin=mysql-bin binlog_format=ROW gtid_mode=ON enforce_gtid_consistency=ON relay_log_recovery=ON slave_parallel_type=LOGICAL_CLOCK slave_parallel_workers=8 read_only=ON super_read_only=ON
3.1.2 輔助腳本
#!/usr/bin/env bash set-euo pipefail MYSQL_CMD="${MYSQL_CMD:-mysql -uroot -p}" OUT_DIR="/tmp/mysql-replica-$(date +%F-%H%M%S)" mkdir -p"$OUT_DIR" $MYSQL_CMD-e"SHOW REPLICA STATUSG">"$OUT_DIR/replica-status.txt" $MYSQL_CMD-e"SHOW PROCESSLIST">"$OUT_DIR/processlist.txt" $MYSQL_CMD-e"SELECT * FROM performance_schema.replication_connection_statusG">"$OUT_DIR/connection-status.txt" $MYSQL_CMD-e"SELECT * FROM performance_schema.replication_applier_status_by_workerG">"$OUT_DIR/applier-status.txt" $MYSQL_CMD-e"SHOW ENGINE INNODB STATUSG">"$OUT_DIR/innodb-status.txt" echo"artifacts saved to$OUT_DIR"
3.2 實(shí)際應(yīng)用案例
案例一:不是網(wǎng)絡(luò)慢,是單個(gè)大事務(wù)把 SQL 線程卡住
場景描述:從庫延遲從幾十毫秒漲到 18 分鐘,主庫沒報(bào)錯(cuò),網(wǎng)絡(luò)也正常。
實(shí)現(xiàn)代碼:
SHOWREPLICASTATUSG SHOWPROCESSLIST; SELECT*FROMinformation_schema.innodb_trxG
運(yùn)行結(jié)果:
Seconds_Behind_Source: 1087 Replica_IO_Running: Yes Replica_SQL_Running: Yes Relay_Log_Space: 1293844832
根因是主庫一次性提交了超大批量更新事務(wù),從庫 SQL 線程長時(shí)間卡在單事務(wù) apply。處理動(dòng)作:
把批處理切小批次
大表更新改成分段執(zhí)行
保留并行復(fù)制但別指望它能拆開單個(gè)超大事務(wù)
案例二:不是 SQL 線程慢,是 IO 線程拉不到新 binlog
場景描述:主從延遲持續(xù)增長,Relay_Log_Space卻不大。
實(shí)現(xiàn)步驟:
看 IO/SQL 線程
SHOWREPLICASTATUSG
看錯(cuò)誤信息
SHOWREPLICASTATUSG
查網(wǎng)絡(luò)和權(quán)限
mysql -hsource-db -e"SHOW BINARY LOG STATUS;" telnetsource-db 3306
根因是復(fù)制鏈路網(wǎng)絡(luò)抖動(dòng)疊加復(fù)制賬號(hào)權(quán)限異常,IO 線程斷續(xù)重連,延遲不斷累積。
案例三:DDL 和元數(shù)據(jù)鎖把復(fù)制線程長期卡住
場景描述:某次結(jié)構(gòu)變更后,從庫延遲持續(xù) 40 多分鐘。IO 線程正常,Relay Log 也在增長,但 SQL 線程一直追不上。
實(shí)現(xiàn)步驟:
看復(fù)制狀態(tài)
SHOWREPLICASTATUSG
查元數(shù)據(jù)鎖和事務(wù)
SELECT*FROMperformance_schema.metadata_locksG SELECT*FROMinformation_schema.innodb_trxG SHOWPROCESSLIST;
看是否被 DDL 卡住
SHOWENGINEINNODBSTATUSG
運(yùn)行結(jié)果:
Waiting for table metadata lock
根因是主庫 DDL 進(jìn)入復(fù)制鏈路后,從庫上又有長查詢占著元數(shù)據(jù)鎖,SQL 線程一直卡在同一條語句。處理動(dòng)作:
先終止阻塞復(fù)制的長查詢
大表 DDL 改到低峰窗口
對(duì)高風(fēng)險(xiǎn) DDL 預(yù)演復(fù)制影響
這類延遲如果只看Seconds_Behind_Source,你知道它慢了,但不知道它為什么永遠(yuǎn)追不上。
四、最佳實(shí)踐和注意事項(xiàng)
4.1 最佳實(shí)踐
4.1.1 性能優(yōu)化
優(yōu)化點(diǎn)一:并行復(fù)制要開,但要結(jié)合業(yè)務(wù)寫入模式驗(yàn)證,熱點(diǎn)表和單大事務(wù)不會(huì)因?yàn)?worker 多就 magically 變快。
優(yōu)化點(diǎn)二:批處理、DDL、大事務(wù)必須做節(jié)流和窗口管理。
優(yōu)化點(diǎn)三:主從延遲監(jiān)控不能只看秒數(shù),還要看 IO/SQL 線程狀態(tài)和 Relay Log 增長速度。
4.1.2 安全加固
安全措施一:從庫保持super_read_only=ON,避免誤寫。
安全措施二:復(fù)制賬號(hào)最小權(quán)限,定期輪換密碼。
安全措施三:復(fù)制鏈路變更先在從庫灰度驗(yàn)證。
4.1.3 高可用配置
HA 方案一:關(guān)鍵讀流量不要只綁一臺(tái)從庫,延遲高時(shí)可自動(dòng)摘流。
HA 方案二:復(fù)制監(jiān)控和業(yè)務(wù)讀延遲監(jiān)控聯(lián)動(dòng)。
備份策略:保留關(guān)鍵時(shí)段SHOW REPLICA STATUS和performance_schema快照。
4.2 注意事項(xiàng)
4.2.1 配置注意事項(xiàng)
警告:Seconds_Behind_Master或Seconds_Behind_Source為0,不等于絕對(duì)沒問題。復(fù)制線程斷開、SQL thread 卡住、延遲剛好被短暫追平,都可能讓你誤判。
大事務(wù)和 DDL 是復(fù)制延遲的常見放大器
并行復(fù)制沒配置好,延遲會(huì)長期追不上
從庫性能不足時(shí),復(fù)制延遲本質(zhì)上是資源問題
4.2.2 常見錯(cuò)誤
| 錯(cuò)誤現(xiàn)象 | 原因分析 | 解決方案 |
|---|---|---|
| 秒數(shù)很高,但線程都正常 | SQL 線程在追大事務(wù) | 查長事務(wù)、DDL、熱點(diǎn)表 |
| 秒數(shù)不高,但讀流量讀到舊數(shù)據(jù) | 監(jiān)控窗口太粗或剛短暫追平 | 增加更細(xì)粒度采樣 |
| Relay Log 持續(xù)增長 | IO 正常拉取,SQL 執(zhí)行跟不上 | 查 apply 能力、鎖等待、資源 |
4.2.3 兼容性問題
版本兼容:8.0 新舊字段名有差異,腳本里要兼容Master/Source命名。
平臺(tái)兼容:云盤性能、跨可用區(qū)網(wǎng)絡(luò)時(shí)延會(huì)直接影響復(fù)制。
組件依賴:GTID、MTS、binlog 格式和 DDL 策略都會(huì)影響復(fù)制行為。
五、故障排查和監(jiān)控
5.1 故障排查
5.1.1 日志查看
grep -Ei'replica|slave|relay|error'/var/log/mysqld.log | tail -50
5.1.2 常見問題排查
問題一:延遲升高,但Relay_Log_Space不大
SHOWREPLICASTATUSG
解決方案:優(yōu)先查 IO 線程、網(wǎng)絡(luò)、權(quán)限、主庫 binlog 獲取。
問題二:Relay_Log_Space很大,秒數(shù)持續(xù)增加
SHOWREPLICASTATUSG SHOWPROCESSLIST;
解決方案:優(yōu)先查 SQL 線程 apply 慢、鎖等待、大事務(wù)。
問題三:并行復(fù)制開了,還是追不上
癥狀:slave_parallel_workers大于 0,但延遲長期不降
排查:
SHOWVARIABLESLIKE'slave_parallel%'; SELECT*FROMperformance_schema.replication_applier_status_by_workerG
解決:判斷寫入是否具備并行空間,熱點(diǎn)表和單大事務(wù)場景要從業(yè)務(wù)側(cè)拆解
5.1.3 調(diào)試模式
SHOWREPLICASTATUSG SHOWENGINEINNODBSTATUSG
5.2 性能監(jiān)控
5.2.1 關(guān)鍵指標(biāo)監(jiān)控
SHOWREPLICASTATUSG
5.2.2 監(jiān)控指標(biāo)說明
| 指標(biāo)名稱 | 正常范圍 | 告警閾值 | 說明 |
|---|---|---|---|
| 復(fù)制延遲秒數(shù) | < 1s | > 10s 持續(xù)5m | 只做結(jié)果告警 |
| IO 線程狀態(tài) | Running | 非 Running | 日志拉取異常 |
| SQL 線程狀態(tài) | Running | 非 Running | Apply 異常 |
| Relay Log 空間 | 平穩(wěn) | 持續(xù)增長15m | 執(zhí)行跟不上 |
5.2.3 監(jiān)控告警配置
groups: -name:mysql-replication rules: -alert:MySQLReplicationLagHigh expr:mysql_slave_status_seconds_behind_master>10 for:5m -alert:MySQLReplicationSQLThreadDown expr:mysql_slave_status_sql_running==0 for:1m -alert:MySQLReplicationIOThreadDown expr:mysql_slave_status_slave_io_running==0 for:1m
5.3 備份與恢復(fù)
5.3.1 備份策略
#!/usr/bin/env bash set-euo pipefail mysql -uroot -p -e"SHOW REPLICA STATUSG"> /backup/replica-status-$(date +%F).txt mysql -uroot -p -e"SHOW MASTER STATUSG"> /backup/master-status-$(date +%F).txt
5.3.2 恢復(fù)流程
采樣現(xiàn)場:bash ./mysql-replica-collect.sh
停止復(fù)制:STOP REPLICA;
修復(fù)根因后恢復(fù):START REPLICA;
驗(yàn)證追平:SHOW REPLICA STATUSG
六、總結(jié)
6.1 技術(shù)要點(diǎn)回顧
主從延遲不能只看秒數(shù)
先分 IO 線程和 SQL 線程,再看 Relay Log 和事務(wù)特征
大事務(wù)、DDL、熱點(diǎn)表是最常見的復(fù)制放大器
并行復(fù)制能提速,但救不了單個(gè)超大事務(wù)
6.2 進(jìn)階學(xué)習(xí)方向
GTID 與復(fù)制拓?fù)渲卫?/strong>
并行復(fù)制與事務(wù)拆分
只讀流量摘流與延遲感知路由
6.3 參考資料
MySQL Replication Status- 復(fù)制狀態(tài)字段說明
Performance Schema Replication Tables- 復(fù)制相關(guān)性能視圖
MySQL Replication Options- 從庫復(fù)制參數(shù)
附錄
A. 命令速查表
SHOWREPLICASTATUSG SHOWPROCESSLIST; SELECT*FROMperformance_schema.replication_connection_statusG SELECT*FROMperformance_schema.replication_applier_status_by_workerG SHOWENGINEINNODBSTATUSG
B. 配置參數(shù)詳解
slave_parallel_workers:并行復(fù)制 worker 數(shù)
relay_log_recovery:異常重啟后 relay log 恢復(fù)
super_read_only:更嚴(yán)格的只讀保護(hù)
C. 術(shù)語表
| 術(shù)語 | 英文 | 解釋 |
|---|---|---|
| 復(fù)制延遲 | Replication Lag | 從庫應(yīng)用事務(wù)落后主庫的時(shí)間差 |
| 中繼日志 | Relay Log | 從庫拉取主庫 binlog 后本地保存的日志 |
| 應(yīng)用線程 | SQL / Applier Thread | 在從庫執(zhí)行事務(wù)的線程 |
| GTID | Global Transaction Identifier | 全局事務(wù)標(biāo)識(shí) |
-
MySQL
+關(guān)注
關(guān)注
1文章
907瀏覽量
29571 -
線程
+關(guān)注
關(guān)注
0文章
510瀏覽量
20829
原文標(biāo)題:MySQL 主從延遲排查全流程:不是只看 Seconds_Behind_Master
文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
簡單介紹MySQL延遲主從復(fù)制
利用MySQL進(jìn)行一主一從的主從復(fù)制
MySQL主從復(fù)制原理詳解
一個(gè)操作把MySQL主從復(fù)制整崩了
MySQL主從延遲排查全流程
評(píng)論