sql线程卡在writing to net或updating且cpu不高是磁盘io瓶颈的典型信号,需结合iostat的await>50ms、%util>95%及sync_relay_log等参数综合诊断。

看SHOW PROCESSLIST里SQL线程状态是否卡在Writing to net或Updating但CPU不高
磁盘IO瓶颈的典型信号不是CPU跑满,而是SQL线程长期停留在Writing to net(实际是写relay log或刷InnoDB脏页)、Updating(执行DML但I/O等待高)这类状态,同时top显示CPU使用率偏低(iostat -x 1中%util持续接近100%、await > 50ms。
-
Writing to net在MySQL 5.7+中常被误读——它实际代表“正在将变更写入存储引擎”,背后可能是InnoDB刷脏页或写redo log,而非网络传输 - 若
Relay_Log_Space持续增长但Exec_Master_Log_Pos几乎不动,基本可锁定是relay log落盘或InnoDB提交慢 - 注意区分:IO线程卡在
Waiting for master to send event是网络问题;SQL线程卡在Writing to net才是本地磁盘IO问题
查iostat -x 1输出中relay log所在磁盘的await和%util
直接定位到relay log路径(SHOW SLAVE STATUS\G里的Relay_Log_File字段,通常在/var/lib/mysql/下),然后盯住对应设备的指标:
-
await > 50ms且波动剧烈 → 单次IO响应过慢,常见于HDD或IOPS超限的云盘 -
%util > 95%持续10秒以上 → 磁盘饱和,无法及时处理写请求 - 对比
r/s(读每秒)和w/s(写每秒):若w/s远高于主库同规格实例的常态值(如>2000 w/s),说明从库写压力异常
确认sync_relay_log和innodb_flush_log_at_trx_commit是否过度保守
这两个参数在从库上设得太严,会把IO压力直接放大:
-
sync_relay_log = 1(默认):每次写relay log都强制刷盘 → 高并发下大量随机小IO -
innodb_flush_log_at_trx_commit = 1:从库没必要强一致性,设为2可大幅降低redo log刷盘频率 - 建议组合:从库设
sync_relay_log = 10000(每万次写刷一次) +sync_relay_log_period = 1000(1秒超时强制刷) +innodb_flush_log_at_trx_commit = 2
排除其他IO干扰:检查Relay_Log_Space暴涨是否伴随tmp_table_sizes或sort_buffer_size滥用
某些大查询(如未加索引的GROUP BY)会在从库产生巨量临时表,写入磁盘临时文件,间接挤占relay log和InnoDB的IO带宽:
- 执行
SHOW GLOBAL STATUS LIKE 'Created_tmp_disk_tables';,若该值每秒增长 > 5,说明有严重临时表落地 - 用
SELECT * FROM performance_schema.events_statements_history_long WHERE SQL_TEXT LIKE '%GROUP BY%' OR SQL_TEXT LIKE '%ORDER BY%' ORDER BY TIMER_WAIT DESC LIMIT 3;定位耗IO的语句 - 报表类查询尽量避开复制高峰期,或改用
read_only=0临时关闭只读限制后,在专用只读实例上跑
真实延迟往往藏在await和sync_relay_log的组合里——很多人调了slave_parallel_workers却没动这两个参数,结果并行线程全在排队等磁盘。











