现场是这样的。阿里云 ESSD 上每天凌晨给系统盘打快照,监控显示打快照的瞬间 MySQL 出现三秒写入停顿,slow log 里同一时间段集中出现大量慢查询。
中间走过弯路,把「快照任务与备份脚本、日志轮转撞在同一时间点,IO 叠加」当成主因,改完现象没变。
真正麻烦的地方在于,几个原因的现象几乎一样。打快照前会短暂冻结文件系统并刷脏页,冻结期间所有写请求挂起;脏页多的时候刷盘时间长,冻结窗口被拉长;云盘本身的突发额度在刷盘时被吃满,恢复写入后还要排队。
上来先确认停顿与快照时间的对应关系
grep -i snapshot /var/log/messages | tail -10 && ls -l /var/log/mysql/slow.log
随后把脏页比例压低,缩短冻结时间
sysctl -w vm.dirty_ratio=10 vm.dirty_background_ratio=5
接着把快照与业务高峰、其他备份任务错开
crontab -l | grep -iE 'backup|snapshot'
剩下的就是打快照前主动同步一次减少脏页
sync && echo 1 > /proc/sys/vm/drop_caches
恢复的判定其实很直接。slow log 中不再出现与快照时间重叠的三秒级慢查询,业务写入的 p99 保持在正常范围,快照任务自身状态为成功。
这里还有个坑。冻结是保证快照一致性的必要代价,缩短窗口比取消更现实;别在同步刷盘时顺手清缓存,drop_caches 在高负载下会带来额外抖动。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。
