一台 CentOS 7 上按老方案把 ext4 的外部日志放在一块 7200 转的机械盘上,业务写入量上来后每次 fsync 要 15ms,pg 和 MySQL 的事务提交都被拖慢。
一开始怀疑是「日志盘与数据盘共用同一个控制器,排队互相影响」,查了一圈,方向不对。
原因不止一个,得分开看。每次事务提交都要等日志写完成,外部日志盘的随机写延迟直接决定提交延迟。少数情况下是机械盘没有写缓存时的寻道时间在 8ms 以上,日志写是小块随机写的最差场景。
还有一种情况,挂载参数 barrier 与 journal 选项叠加,多了一次同步等待。
上来先确认日志设备与挂载参数
dumpe2fs -h /dev/vdb1 | grep -i journal && findmnt -o OPTIONS /data
实测该盘的随机写延迟
dd if=/dev/zero of=/journal/test bs=4k count=1000 oflag=direct,dsync
然后把日志迁回数据盘或者换 SSD
tune2fs -O ^has_journal /dev/vdb1 && tune2fs -j /dev/vdb1
等前面都确认过,再确认日志位置与提交延迟
dumpe2fs -h /dev/vdb1 | grep -i 'journal' && grep -E 'Dirty|Writeback' /proc/meminfo
改完先别撤,确认这几项。dd 的 4K 同步写延迟降到 1ms 以内,业务事务提交时间回到正常区间,/proc/meminfo 里 Dirty 不再长时间堆积。
外置日志只在早期机械盘阵列上有意义,SSD 时代反而增加一次远程写;迁移日志必须卸载分区并用 tune2fs 重建,不能在线改。报错文案容易误导,真正的原因往往在相邻那一层的日志里。
