mysqldump全量备份必然冲高io,因其本质是串行select查询,逐表读取数据页,不缓存、不跳过、不压缩;必须用pv接在stdout管道中限速(如mysqldump | pv -l 10m > backup.sql),配合ionice分层控制,否则仅调参数无效。

直接用 mysqldump 全量备份,IO 必然冲高;必须改用管道流控 + 进程调度组合策略,否则再调参数也没用。
为什么 mysqldump 会把磁盘 IO 打满
它本质是串行 SELECT 查询,逐表读取数据页,不缓存、不跳过、不压缩——尤其在机械盘或高负载 SSD 上,r_await 和 aqu-sz 会快速飙升。即使加了 --single-transaction,InnoDB 仍要遍历 undo log 构建一致性视图,IO 压力一点没少。
- 全库导出时,
iostat -x 1中的wMB/s常突破磁盘写入能力上限 -
mysqldump不支持原生命令限速(比如没有--throttle),传任何不认识的参数都会被忽略 - 重定向写文件(
mysqldump > backup.sql)会让 pv 完全失效——因为重定向早于管道执行
必须用 pv 接在 stdout 管道里限速
pv 是唯一能实时掐住 mysqldump 输出流速的通用工具,但它只对管道生效,不能作用于文件写入。
- 正确写法:
mysqldump --single-transaction --all-databases | pv -L 10m > backup.sql -
-L 10m中的m必须带单位,否则按字节/秒算(-L 10= 10B/s,等于卡死) - 若要压缩,
pv必须在gzip前:mysqldump | pv -L 8m | gzip > backup.sql.gz - 实测:设
-L 8m后,aqu-sz从 6+ 降到 1.3 左右,w_await从 40ms+ 回落至 6~9ms
搭配 ionice 控制调度优先级
pv 管流速,ionice 管时间片,两者不是互斥而是分层压制。
- 推荐组合:
ionice -c2 -n7 mysqldump | pv -L 8m > backup.sql - 别用
-c3(idle class):MySQL 自身刷日志(innodb_log_flush)可能被饿死,引发innodb_log_waits上升 - 高峰期大库(>100GB)建议先
ionice再pv;低峰期小库单用pv -L 15m即可 - 验证是否生效:盯
iostat的aqu-sz,持续 >2 超过 10 秒说明限速值还是偏高
更彻底的方案:换物理备份 + 专用从库
如果业务真扛不住任何 IO 波动,mysqldump 就不该出现在主库上。
- 用
xtrabackup --throttle=100(单位是页/秒),比pv更底层、更稳定 - 备份源切到只读从库:
STOP SLAVE SQL_THREAD后立即备份,确保点一致 - 从库本身不对外提供读服务,避免其他查询干扰备份 IO
- 注意校验
Seconds_Behind_Master,必须 ≈ 0,否则备份的是延迟数据
真正容易被忽略的点是:限速值不能拍脑袋定。USB 机械盘上设 -L 20m 只会让 pv 缓冲区堆积,反而放大延迟;而 SSD 上设太低又浪费带宽。得结合 iostat -x 1 实时看 aqu-sz 和 w_await 动态调。











