MySQL 从库延迟 10 小时——磁盘静默错误引发的惨案
事发:周一早会,BI 组吐槽报表“昨天的数据对不上”。看监控,从库
Seconds_Behind_Master
飙到 3 万秒,IO 线程正常,SQL 线程卡在Updating
。没报警,因为延迟曲线是“慢慢涨”,不是陡增。把排查步骤留底,脚本可直接跑。
1. 先看 SQL 线程在执行啥
SHOW PROCESSLIST\G
State: Updating
Info: UPDATE large_stat SET uv=uv+1 WHERE id=123456
一条简单更新卡 10 s,肯定不对劲。
2. 找慢原因
SHOW ENGINE INNODB STATUS\G
---TRANSACTION 3147483647
, ACTIVE 11 sec
fetching rows
0.1 sec,但 updating
10.9 sec,怀疑磁盘。
3. 测磁盘延迟
apt install fio
fio --name=randwrite --rw=randwrite --bs=4k --size=1G --ioengine=libaio --direct=1 --numjobs=1 --time_based --runtime=60 --group_reporting
lat (usec): mean=1800
同型号盘,正常值 80 µs,现在是 20 倍,SMART 还没报警:
smartctl -a /dev/sdb | grep Reallocated5 Reallocated_Sector_Ct 0x0033 100 100 010 Pre-fail Always - 0
表面健康,实际掉速——典型的“静默错误”。
4. 确认表坏没坏
CHECKSUM TABLE large_stat;
从库校验值 0xA5BC6712,主库 0xD38F9945,数据已不一致。
由于 ROW 格式,SQL 线程重放时找不到对应行,全表扫描,延迟越拖越大。
5. 快速修复
- 停 SQL 线程
STOP SLAVE SQL_THREAD;
- 用
pt-table-checksum
在主库扫差异:pt-table-checksum --replicate=percona.checksums --no-check-binlog-format
- 生成补偿 SQL:
pt-table-sync --replicate=percona.checksums --print --sync-to-master h=slave_ip,u=checksum,p=xxx
- 导出差量 1.3 GB,直接管道灌回从库:
pt-table-sync ... --execute
- 开 SQL 线程,延迟从 3 万秒掉到 0 秒,耗时 40 min。
6. 换盘 + 改架构
- 把
/dev/sdb
拿下,厂商检测后确认固件 BUG,批量掉速,免费换新。 - 从库改 RAID10,宁可损失 50% 容量,也要把静默错误概率压下去。
- 写个 15 行的 Python 脚本,用
SHOW STATUS
取Innodb_buffer_pool_reads
,除以Uptime
,大于 300 次/秒就发短信——磁盘突然掉速时,这个比值会陡升,比 SMART 报警早 2 小时。
#!/usr/bin/env python3
import time, pymysql, requests
db = pymysql.connect(host='127.0.0.1', user='monitor', passwd='xxx', db='')
while True:with db.cursor() as c:c.execute("SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_reads'")reads1 = int(c.fetchone()[1])c.execute("SHOW GLOBAL STATUS LIKE 'Uptime'")up1 = int(c.fetchone()[1])time.sleep(300)with db.cursor() as c:c.execute("SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_reads'")reads2 = int(c.fetchone()[1])c.execute("SHOW GLOBAL STATUS LIKE 'Uptime'")up2 = int(c.fetchone()[1])rps = (reads2 - reads1) / (up2 - up1)if rps > 300:requests.post("https://sms-api.xxx/send", data={"msg": "从库磁盘可能掉速"})
7. 后续
- 主从校验加到周任务,差异超过 100 行自动发 ticket。
- 把只读查询拆到“群联 AI 云防护”后面的只读节点,云端顺便做 SQL 审计,SELECT 不带 WHERE 直接拒绝,还能顺手挡注入。
- 云防护给的高防 IP 把 3306 隐藏,扫描器再也扫不到真实库,减少无谓爆破。
一句话总结
从库延迟高不一定是大事务,也可能是磁盘“慢病”;提前把物理盘 RAID 化、把只读流量甩到云端,比事后追数据省心一百倍。