MySQL 的 redo 落在 ext4 上,业务侧偶发单条写入 200ms,iostat 的 await 也跟着尖刺,排查到挂载参数是默认的 commit=5,盘本身是 ESSD,随机写能力并不差。

一开始怀疑是「journal 的 data=ordered 模式让数据块先写,日志提交被拖后」,查了一圈,方向不对。

原因不止一个,得分开看。ext4 每 5 秒才提交一次日志,fsync 要等这一轮才返回。少数情况下是barrier 开着但云盘的写缓存策略与它对不上,提交被反复拖延。

不容易想到的是,同一分区上还有别的进程在大量写,日志队列排队。

第一件事是看挂载参数和日志提交设置

findmnt -T /var/lib/mysql -o OPTIONS && grep mysql /proc/mounts

接着用带 fsync 的方式实测延迟分布

fio --name=fs --rw=write --bs=4k --size=512M --fsync=16 --runtime=30 --time_based

再往下把数据目录换到独立分区减少干扰

grep -n '/var/lib/mysql' /etc/fstab

调整提交间隔并观察尖刺

mount -o remount,commit=1 /data

别只看报错消失,验证要多做一步。fio 的 99 分位延迟从 200ms 降到 20ms 以内,业务侧不再出现单条写入超时,iostat 的 await 曲线变平。

commit 调小会增加日志写入次数,写放大和盘寿命都要考虑;根治办法是把数据库放在独立盘上,别和日志共用一个文件系统。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。

作者 9823189