scrub 不会卡死系统但会打满磁盘io,需用 ionice -c2 -n7 限速;balance 仅在 chunk 碎片、分布不均或设备故障时才需运行;scrub 与 balance 必须串行且先 scrub 后 balance。

scrub 会卡住系统吗?IO 负载怎么压下来
不会直接卡死,但默认跑法会让磁盘 IO 持续打满,尤其在机械盘或混用负载的机器上,rsync、postgres 这类服务响应会明显变慢。
关键不是“做不做”,而是“怎么限速”。btrfs scrub 本身不支持 --throttle 或类似参数,得靠外部工具控速:
- 用
ionice -c2 -n7降低 IO 调度优先级(推荐,对交互影响最小) - 配合
cpulimit没用——scrub 是 IO 密集型,CPU 占用通常不到 5% - 避免在
/proc/sys/vm/swappiness高的机器上跑,swap 活跃时 scrub 可能触发内存回收抖动
示例命令:
ionice -c2 -n7 btrfs scrub start -B /mnt/data(
-B 表示前台运行,方便配合 ionice)
balance 什么时候必须跑?哪些 filter 真的有用
不是定期跑就有益。btrfs balance 主要解决两类问题:碎片导致的写放大、chunk 分布不均引发的单盘过载。80% 的误操作源于把它当“磁盘整理”用。
真正需要 balance 的信号只有三个:
-
btrfs filesystem usage /path显示某块 device 的used接近 100%,但其他盘还有空闲 - 写入大量小文件后,
btrfs filesystem df /path中Data类型的total远大于used(说明 chunk 碎片严重) - 执行
btrfs device stats /path发现某设备有持续read_failures,balance 可强制迁移该设备上的 chunk(但先确认硬件没坏)
常用 filter 中,usage=85 和 profiles=dup 最实用;limit=100 这种纯数字限制容易误伤——它按 chunk 数计,不是按空间算。
scrub 和 balance 能不能一起跑?顺序有讲究吗
绝对不要并发执行。两者都会读写 chunk tree 和 extent tree,同时跑大概率触发 transaction aborted 错误,日志里出现 aborting transaction 就是这个原因。
必须串行,且顺序固定:
- 先
btrfs scrub—— 它只读,能发现静默数据损坏,是 balance 前的安全检查 - 等 scrub 完成且无
errors(查btrfs scrub status /path),再跑btrfs balance - balance 完了最好再 scrub 一次,验证迁移后的数据一致性
中间任意一步失败,就停住。balance 半途被 kill 可能留下 inconsistent chunk tree,恢复起来比重做还麻烦。
crontab 里怎么写才不算耍流氓
直接写 0 2 * * 0 btrfs scrub start /mnt/data 是典型反模式:没检查挂载状态、没处理锁冲突、没防 overlap。
一个可用的最小化脚本逻辑:
- 用
findmnt -T /mnt/data确认路径已挂载且是 btrfs - 检查
/var/run/btrfs-scrub.lock是否存在(自己建个简单锁文件) - 加
timeout 24h防止 scrub 卡死(某些坏块场景下会 hang 住) - 把输出重定向到
/var/log/btrfs-scrub.log,别丢进/dev/null
IO 影响最隐蔽的点:balance 默认使用 metadata 和 system profile 的 full write,即使你只 filter data chunk,它仍会重写所有 metadata。这意味着 SSD 的写入放大和寿命消耗比看起来高得多。










