最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MySQL主從延遲根因定位排查大法

 更新時間:2026年07月14日 10:50:35   作者:做個文藝程序員  
主從延遲作為MySQL的痛點已經存在很多年了,以至于大家都有一種錯覺,有MySQL復制的地方就有主從延遲,這篇文章主要介紹了MySQL主從延遲根因定位排查的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下

一、先量化延遲:別被假數據騙了

排查延遲的第一步,是拿到真實可信的延遲數值。

1.1 Seconds_Behind_Master 的局限

SHOW SLAVE STATUS\G
-- 關注字段:Seconds_Behind_Master

這個值有一個致命缺陷:當 SQL 線程卡住時,它會停止更新,導致顯示值失真。在大事務或 DDL 阻塞場景下,它可能長時間靜止不動,但實際延遲仍在累積。

1.2 推薦:pt-heartbeat(精準測量)

# 主庫:持續(xù)寫入心跳
pt-heartbeat --user=root --password=xxx --host=master \
  --database=test --create-table --daemonize --update

# 從庫:實時讀取延遲
pt-heartbeat --user=root --password=xxx --host=slave \
  --database=test --monitor --master-server-id=1

pt-heartbeat 的優(yōu)勢:

  • 跨時區(qū)安全,不依賴系統時鐘
  • 精確到毫秒級
  • SQL 線程卡住時依然能反映真實延遲

二、三層定位法:快速鎖定瓶頸層次

拿到延遲數值后,執(zhí)行以下語句,對照兩個關鍵位點判斷延遲來自哪一層:

SHOW SLAVE STATUS\G
對比位點差距大說明延遲層次
Master_Log_File vs Relay_Master_Log_Filebinlog 沒傳過來網絡層 / IO 線程
Relay_Log_File vs Exec_Master_Log_Filerelay log 沒回放完SQL 線程
主庫寫入 → [網絡傳輸] → IO線程接收 → relay log → [SQL線程回放] → 從庫執(zhí)行
            ↑ 第一段延遲                              ↑ 第二段延遲

三、網絡層排查

3.1 診斷命令

# 測試帶寬(雙向)
iperf3 -c master_ip -t 30

# 檢查 RTT 和丟包
ping master_ip -c 100

# 查看網卡實時流量
sar -n DEV 1 10

3.2 常見問題與對策

帶寬不足:binlog 產生速度 > 網絡傳輸速度

# my.cnf 從庫配置:開啟壓縮傳輸(CPU 換帶寬)
[mysqld]
slave_compressed_protocol = ON

網絡抖動導致重連慢

# 縮短重連超時(默認 60s 太長)
slave_net_timeout = 30

跨機房場景:優(yōu)先申請專線或使用 VPN 隔離,避免公網延遲抖動。

四、IO 線程層排查

IO 線程慢的本質是:主庫 binlog 產生速度 > IO 線程接收寫入速度

4.1 檢查 binlog 產生速率

# 主庫:觀察 binlog 增長速度
mysqlbinlog --start-datetime="2024-01-01 10:00:00" \
            --stop-datetime="2024-01-01 10:01:00" \
            /var/lib/mysql/mysql-bin.000001 | wc -c

4.2 binlog_format 的影響

formatevent 大小對延遲影響
STATEMENT?。ㄖ挥?SQL)低帶寬,但有安全風險
ROW大(記錄行變更)帶寬消耗高,適合高一致性要求
MIXED折中推薦默認
binlog_format = ROW          # 高一致性場景
binlog_row_image = MINIMAL   # 減少 ROW 模式下的 event 大?。∕ySQL 5.6+)

4.3 主庫刷盤參數

# 主庫:高性能寫入(權衡持久性)
sync_binlog = 0                         # 0=OS 決定刷盤時機,性能最高
innodb_flush_log_at_trx_commit = 2      # 每秒刷盤,非每次事務

# 主庫:高安全(金融場景)
sync_binlog = 1
innodb_flush_log_at_trx_commit = 1

五、SQL 線程層排查(最常見根因)

這是高并發(fā)場景最普遍的瓶頸。主庫多線程并發(fā)寫入,從庫默認單線程串行回放,必然追不上。

5.1 確認 SQL 線程是瓶頸

-- 確認 SQL 線程正在運行但回放慢
SHOW SLAVE STATUS\G
-- Slave_SQL_Running: Yes
-- Exec_Master_Log_Pos 長期落后 Relay_Log_Pos

5.2 開啟并行復制(核心解法)

MySQL 5.7+ 基于邏輯時鐘的并行復制(推薦):

[mysqld]
# 從庫配置
slave_parallel_type     = LOGICAL_CLOCK   # 基于 binlog group commit 信息
slave_parallel_workers  = 8               # 從 CPU 核數 50% 開始調,逐步壓測
slave_preserve_commit_order = ON          # 保證從庫事務提交順序與主庫一致

# 主庫需配合(提高 group commit 批量)
binlog_group_commit_sync_delay    = 100   # 微秒,等待更多事務進組
binlog_group_commit_sync_no_delay_count = 10

?? 注意slave_preserve_commit_order = ON 必須開啟,否則從庫事務順序與主庫不一致,可能導致讀到臟數據。

5.3 驗證并行復制效果

-- 查看并行復制工作線程狀態(tài)
SELECT * FROM performance_schema.replication_applier_status_by_worker\G

-- 查看 worker 線程分配情況
SHOW STATUS LIKE 'Slave_worker%';

5.4 MySQL 8.0 的改進

MySQL 8.0 引入 Writeset 并行復制,不依賴 group commit,并行度更高:

binlog_transaction_dependency_tracking = WRITESET
slave_parallel_type                    = LOGICAL_CLOCK
slave_parallel_workers                 = 16

六、深層陷阱:大事務 / 鎖競爭 / DDL / 磁盤 IO

6.1 大事務(最常被忽略的殺手)

大事務在主庫被多線程并發(fā)所掩蓋,到從庫單線程串行回放時會產生秒級甚至分鐘級卡頓。

定位大事務

# 找到 binlog 中的超大 event
mysqlbinlog --verbose /var/lib/mysql/mysql-bin.000001 \
  | awk '/^# at/{pos=$3} /^### /{count++} /^COMMIT/{if(count>10000) print pos, count; count=0}'

# 或用 mysqlbinlog 直接統計
mysqlbinlog --base64-output=DECODE-ROWS -v mysql-bin.000001 \
  | grep -E "^(# at|^### )" | awk '...'

業(yè)務層改造

-- ? 危險:一次刪除 500 萬行
DELETE FROM orders WHERE created_at < '2023-01-01';

-- ? 安全:分批刪除,每批 1000 行
DELETE FROM orders WHERE created_at < '2023-01-01' LIMIT 1000;
-- 循環(huán)執(zhí)行直到影響行數為 0

6.2 鎖競爭(從庫上的讀寫沖突)

從庫并非只讀——備份、統計查詢會產生鎖,與 SQL 線程的寫操作產生沖突。

-- 查看從庫當前鎖等待
SELECT 
  r.trx_id waiting_trx_id,
  r.trx_mysql_thread_id waiting_thread,
  r.trx_query waiting_query,
  b.trx_id blocking_trx_id,
  b.trx_mysql_thread_id blocking_thread
FROM information_schema.INNODB_TRX b
JOIN information_schema.INNODB_TRX r ON r.trx_wait_started IS NOT NULL;

對策

  • 從庫大查詢使用 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
  • 備份使用 --single-transaction 避免持鎖
  • 將分析查詢遷移到專用的只讀從庫

6.3 DDL 阻塞

原生 DDL 在從庫執(zhí)行時會獨占 SQL 線程,期間所有回放暫停。

# 推薦:使用 gh-ost 進行在線表變更(不阻塞從庫)
gh-ost \
  --host=master \
  --user=root --password=xxx \
  --database=mydb \
  --table=orders \
  --alter="ADD INDEX idx_user_id(user_id)" \
  --execute

或使用 Percona 的 pt-online-schema-change

pt-online-schema-change \
  --alter="ADD INDEX idx_user_id(user_id)" \
  D=mydb,t=orders \
  --execute

6.4 磁盤 IO 瓶頸

# 實時觀察磁盤 IO
iostat -xm 1 10

# 找到 IO 最多的進程
iotop -o

# 查看 MySQL 數據目錄所在磁盤
df -h /var/lib/mysql

關鍵參數

# 從庫可以適當降低持久性換性能
innodb_flush_log_at_trx_commit = 2    # 從庫安全降級
innodb_flush_method            = O_DIRECT
innodb_io_capacity             = 4000  # SSD 場景可調高至 8000-20000
innodb_io_capacity_max         = 8000

七、關鍵參數速查表

參數推薦值作用適用位置
slave_parallel_workers4 ~ 16并行回放線程數從庫
slave_parallel_typeLOGICAL_CLOCK并行復制策略從庫
slave_preserve_commit_orderON保證事務順序從庫
sync_binlog1(安全)/ 0(性能)主庫 binlog 刷盤主庫
innodb_flush_log_at_trx_commit1(主庫)/ 2(從庫)redo log 刷盤主 / 從
slave_net_timeout30網絡超時重連從庫
relay_log_recoveryON從庫重啟自動修復從庫
slave_compressed_protocolON(跨機房)壓縮傳輸節(jié)省帶寬從庫
binlog_row_imageMINIMAL減小 ROW 格式 event主庫
innodb_io_capacity4000 ~ 20000(SSD)IO 調度上限從庫

八、監(jiān)控告警體系搭建

8.1 Prometheus + mysqld_exporter

# prometheus.yml 抓取配置
scrape_configs:
  - job_name: 'mysql_slave'
    static_configs:
      - targets: ['slave_host:9104']

核心監(jiān)控指標

# 從庫延遲
mysql_slave_status_seconds_behind_master

# IO 線程狀態(tài)(1=Running,0=異常)
mysql_slave_status_slave_io_running

# SQL 線程狀態(tài)
mysql_slave_status_slave_sql_running

# 并行復制 worker 等待
mysql_slave_status_slave_worker_count

8.2 Grafana 告警規(guī)則建議

# 告警閾值參考
- alert: MySQLReplicationLagWarning
  expr: mysql_slave_status_seconds_behind_master > 10
  for: 2m
  annotations:
    summary: "從庫延遲超過 10s,當前值 {{ $value }}s"

- alert: MySQLReplicationLagCritical
  expr: mysql_slave_status_seconds_behind_master > 30
  for: 1m
  annotations:
    summary: "從庫延遲超過 30s(嚴重),當前值 {{ $value }}s"

- alert: MySQLReplicationThreadDown
  expr: mysql_slave_status_slave_sql_running == 0 or mysql_slave_status_slave_io_running == 0
  for: 30s
  annotations:
    summary: "主從復制線程已停止"

8.3 pt-heartbeat 集成

# 主庫(systemd 守護進程)
pt-heartbeat --update --host=master --database=test \
             --create-table --daemonize \
             --pid=/var/run/pt-heartbeat.pid

# 從庫監(jiān)控(輸出毫秒級精度)
pt-heartbeat --monitor --host=slave --database=test \
             --master-server-id=1 --frames=1m,5m,15m

九、建立持續(xù)治理 SOP

解決延遲不是一次性的,需要建立持續(xù)治理機制

變更管控

  • DDL 變更必須走審批流,使用 gh-ostpt-osc
  • 批量寫入操作必須分批,單批不超過 1000 行
  • 高峰期禁止大批量刪除/更新

容量規(guī)劃

  • 主庫寫入 QPS 增長超過 20%,及時評估并行復制 worker 數量
  • 監(jiān)控 binlog 產生速率,提前規(guī)劃磁盤和帶寬

定期演練

  • 每季度模擬延遲場景,驗證告警鏈路是否暢通
  • 記錄歷史延遲事件的根因和恢復時間(MTTR)

總結

主從延遲排查可以遵循以下優(yōu)先級:

1. 量化延遲(pt-heartbeat 優(yōu)于 Seconds_Behind_Master)
2. 用 SHOW SLAVE STATUS 定層(網絡 / IO 線程 / SQL 線程)
3. SQL 線程慢 → 優(yōu)先開并行復制(80% 場景的解法)
4. 排查大事務 → 業(yè)務改造分批寫
5. 檢查鎖競爭 → 減少從庫查詢干擾
6. DDL 變更 → 使用 gh-ost / pt-osc
7. 磁盤 IO → 升級 SSD + 調整 innodb_io_capacity

主從延遲沒有銀彈,需要結合業(yè)務寫入模式、硬件配置和 MySQL 版本綜合調優(yōu)。建議從并行復制入手,再逐步收斂到大事務治理和監(jiān)控體系完善。

到此這篇關于MySQL主從延遲根因定位排查大法的文章就介紹到這了,更多相關MySQL主從延遲排查內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • mysql中取出json字段的小技巧

    mysql中取出json字段的小技巧

    這篇文章主要介紹了mysql中取出json字段的小技巧,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • 淺談MySQL和Lucene索引的對比分析

    淺談MySQL和Lucene索引的對比分析

    下面小編就為大家?guī)硪黄狹ySQL和Lucene索引的對比分析。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-09-09
  • MySQL優(yōu)化SQL語句的技巧

    MySQL優(yōu)化SQL語句的技巧

    這篇文章主要介紹了常見優(yōu)化SQL語句的技巧,幫助大家更好的提高數據庫的性能,感興趣的朋友可以了解下
    2020-08-08
  • 解決MySQL導入SQL時報錯1067–Invalid default value for ‘ ’問題

    解決MySQL導入SQL時報錯1067–Invalid default value for

    文章介紹了MySQL中報錯[ERR]1067-Invaliddefaultvaluefor‘add_date’的原因,以及如何通過修改my.ini文件禁用嚴格模式來解決這個問題
    2026-03-03
  • MYSQL必知必會讀書筆記第三章之顯示數據庫

    MYSQL必知必會讀書筆記第三章之顯示數據庫

    MySQL是一種開放源代碼的關系型數據庫管理系統(RDBMS),MySQL數據庫系統使用最常用的數據庫管理語言--結構化查詢語言(SQL)進行數據庫管理。接下來通過本文給大家介紹MYSQL必知必會讀書筆記第三章之顯示數據庫,感興趣的朋友參考下吧
    2016-05-05
  • 詳解MySQL8中的新特性窗口函數

    詳解MySQL8中的新特性窗口函數

    MySQL8?窗口函數是一種特殊的函數,它可以在一組查詢行上執(zhí)行類似于聚合的操作,但是不會將查詢行折疊為單個輸出行,而是為每個查詢行生成一個結果,本文就來和大家簡單講講它的用法,感興趣的可以了解一下
    2023-06-06
  • 詳解mysql 使用left join添加where條件的問題分析

    詳解mysql 使用left join添加where條件的問題分析

    這篇文章主要介紹了詳解mysql 使用left join添加where條件的問題分析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-02-02
  • 一文詳解MYSQL最樸素的監(jiān)控方式

    一文詳解MYSQL最樸素的監(jiān)控方式

    對于當前數據庫的監(jiān)控方式有很多,分為數據庫自帶、商用、開源三大類,每一種都有各自的特色,那我們今天就介紹一下完全采用mysql自有方式采集獲取監(jiān)控數據,在單體下達到最快速、方便、損耗最小,感興趣的同學可以借鑒閱讀
    2023-05-05
  • MySQL定時備份到本地實現方式

    MySQL定時備份到本地實現方式

    項目使用mysqldump工具定時備份數據庫至本地,腳本mysql-backup.sh包含刪除歷史備份數據的命令,并通過定時任務實現自動化備份流程,確保數據安全與存儲空間管理
    2025-09-09
  • Mysql中LAST_INSERT_ID()的函數使用詳解

    Mysql中LAST_INSERT_ID()的函數使用詳解

    從名字可以看出,LAST_INSERT_ID即為最后插入的ID值,有了這個實用的函數,我們可以實現很多問題,下面我們就來深入探討下。
    2015-03-03

最新評論

花垣县| 柘城县| 平武县| 奈曼旗| 松桃| 苗栗县| 黑河市| 莱西市| 临湘市| 黎平县| 南江县| 富顺县| 华蓥市| 增城市| 长春市| 察哈| 皋兰县| 马边| 商水县| 镶黄旗| 香格里拉县| 仪征市| 民勤县| 盐亭县| 兴安盟| 淄博市| 祥云县| 台安县| 蒙阴县| 乌鲁木齐市| 百色市| 鸡东县| 抚州市| 千阳县| 乌兰察布市| 安龙县| 石景山区| 根河市| 涟水县| 宁国市| 犍为县|