强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Btrfs 文件系统运维完全教程 / 第 8 章:数据校验 (Scrub)

第 8 章:数据校验 (Scrub)

8.1 Scrub 概述

8.1.1 什么是 Scrub

Scrub 是 Btrfs 的定期数据校验机制,通过读取所有数据块并验证校验和,主动发现和修复静默数据损坏(Silent Data Corruption)。

8.1.2 为什么需要 Scrub

数据损坏类型 说明 Scrub 是否能发现
位翻转(Bit Rot) 存储介质自然老化
写入不完整 断电或固件 bug
DMA 传输错误 内存/总线错误
固件 bug 磁盘控制器错误
恶意篡改 人为修改数据
磁盘扇区坏块 物理损坏

8.1.3 工作原理

Scrub 流程:
1. 扫描文件系统的所有 extent
2. 读取每个 extent 的数据
3. 计算校验和(CRC32C / xxhash / sha256 / blake2b)
4. 与元数据中存储的校验和比较
5. 如果不匹配:
   a. RAID 1/10:从其他副本修复
   b. 单设备模式:报告错误
6. 记录结果到统计信息

8.2 执行 Scrub

8.2.1 启动 Scrub

# 启动 scrub(后台运行)
sudo btrfs scrub start /mnt/data

# 启动并等待完成
sudo btrfs scrub start -B /mnt/data

# 只 scrub 指定设备
sudo btrfs scrub start -d /dev/sdb /mnt/data

# 限制 scrub 速度(降低对业务的影响)
sudo btrfs scrub start -c 2 /mnt/data  # 限制 2 个并发

# 设置 IO 优先级(需要 ionice 支持)
sudo ionice -c 3 btrfs scrub start /mnt/data

8.2.2 查看 Scrub 状态

# 查看当前 scrub 状态
sudo btrfs scrub status /mnt/data

# 输出示例:
# UUID:             a1b2c3d4-e5f6-7890-abcd-ef1234567890
# Scrub started:    Sat May 10 02:00:00 2026
# Status:           running
# Duration:         0:35:22
# Total to scrub:   100.00GiB
# Rate:             48.50MiB/s
# Error summary:    no errors found

# 查看历史 scrub 结果
sudo btrfs scrub status -d /mnt/data

8.2.3 取消 Scrub

# 取消正在进行的 scrub
sudo btrfs scrub cancel /mnt/data

8.3 Scrub 错误处理

8.3.1 错误类型

错误类型 说明 严重程度
csum (校验和错误) 读取数据的校验和与存储的不匹配
super (超级块错误) 超级块损坏 严重
verify (验证错误) 元数据验证失败
read (读取错误) 物理读取失败 严重
csum (已修复) 从其他副本修复成功 信息

8.3.2 查看 Scrub 错误

# 查看 scrub 错误详情
sudo btrfs scrub status -d /mnt/data

# 输出中错误示例:
# Scrub device /dev/sdb (id 1) history
# Scrub started:    Sat May 10 02:00:00 2026
# Status:           finished
# Duration:         0:35:22
# Total to scrub:   100.00GiB
# Rate:             48.50MiB/s
# Error summary:    csum=3
#   Corrected:      2
#   Uncorrectable:  1
#   Unverified:     0

# 查看设备错误统计
sudo btrfs device stats /mnt/data

8.3.3 修复错误

单设备模式(无法自动修复)

# 如果 scrub 发现错误且无法修复
# 1. 立即备份数据
sudo rsync -av /mnt/data/ /backup/

# 2. 检查文件系统
sudo umount /mnt/data
sudo btrfs check /dev/sdb1

# 3. 如果 check 报错
sudo btrfs check --repair /dev/sdb1  # ⚠️ 危险操作

RAID 1 模式(自动修复)

# RAID 1 模式下,scrub 会自动从其他副本修复损坏的数据
# scrub 结果中 "Corrected" 数量会增加

# 查看修复详情
sudo btrfs device stats /mnt/data
# [/dev/sdb].corruption_errs  3   ← 检测到 3 个损坏
# [/dev/sdc].corruption_errs  0

# 修复后的数据已经写回正确的副本

8.4 定期 Scrub 调度

8.4.1 推荐调度频率

场景 建议频率 原因
生产服务器 每周 1-2 次 数据完整性至关重要
NAS / 文件服务器 每周 1 次 大量数据需要保护
SSD 存储 每月 1 次 SSD 出错概率较低
归档存储 每月 1 次 数据变更少
桌面系统 每月 1 次 非关键数据

8.4.2 systemd 定时器配置

# /etc/systemd/system/btrfs-scrub@.timer
[Unit]
Description=Btrfs scrub timer for %i

[Timer]
OnCalendar=weekly
RandomizedDelaySec=3600
Persistent=true

[Install]
WantedBy=timers.target
# /etc/systemd/system/btrfs-scrub@.service
[Unit]
Description=Btrfs scrub for %i

[Service]
Type=oneshot
ExecStart=/usr/bin/btrfs scrub start -B %i
Nice=19
IOSchedulingClass=idle
# 启用 scrub 定时器
sudo systemctl enable --now btrfs-scrub@mnt-data.timer

# 检查定时器状态
sudo systemctl list-timers btrfs-scrub@mnt-data.timer

8.4.3 Cron 调度

# 每周日凌晨 2 点执行 scrub
0 2 * * 0 /usr/bin/btrfs scrub start -B /data 2>&1 | logger -t btrfs-scrub

# 每月 1 号凌晨 3 点(SSD)
0 3 1 * * /usr/bin/btrfs scrub start -B /data 2>&1 | logger -t btrfs-scrub

8.4.4 综合 Scrub 脚本

#!/bin/bash
# btrfs-scrub-wrapper.sh - 带通知的 Scrub 脚本
set -euo pipefail

MOUNT_POINT="${1:?Usage: $0 /mount/point}"
ALERT_EMAIL="${2:-admin@example.com}"
LOG_FILE="/var/log/btrfs-scrub.log"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}

send_alert() {
    local subject="$1"
    local body="$2"
    echo "$body" | mail -s "Btrfs Scrub: $subject" "$ALERT_EMAIL"
}

log "Starting scrub on $MOUNT_POINT"

# 执行 scrub
OUTPUT=$(sudo btrfs scrub start -B "$MOUNT_POINT" 2>&1) || true
log "$OUTPUT"

# 检查结果
STATUS=$(sudo btrfs scrub status "$MOUNT_POINT" 2>&1)
log "$STATUS"

# 检查错误统计
ERRORS=$(sudo btrfs device stats "$MOUNT_POINT" 2>&1)
TOTAL_ERRORS=$(echo "$ERRORS" | grep -v " 0$" | grep -v "^[/" | wc -l)

if [[ "$TOTAL_ERRORS" -gt 0 ]]; then
    log "WARNING: Device errors detected!"
    log "$ERRORS"
    send_alert "Scrub completed with errors on $MOUNT_POINT" \
        "Scrub output:\n$OUTPUT\n\nDevice stats:\n$ERRORS"
else
    log "Scrub completed successfully, no errors found."
fi

8.5 Scrub 性能影响

8.5.1 资源消耗

资源 影响 说明
CPU 中等 校验和计算
内存 仅读取缓存
磁盘 I/O 顺序读取所有数据
网络(NFS) 如果通过网络挂载

8.5.2 降低 Scrub 影响

# 方法 1:降低优先级
sudo ionice -c 3 btrfs scrub start /mnt/data
sudo nice -n 19 btrfs scrub start /mnt/data

# 方法 2:限制并发设备数
sudo btrfs scrub start -c 1 /mnt/data

# 方法 3:选择低峰期执行
# cron 中设置在凌晨执行
0 2 * * 0 /usr/bin/btrfs scrub start -B /data

8.5.3 Scrub 速度参考

设备类型 大约速度 100GB 耗时
NVMe SSD 500-2000 MiB/s 1-3 分钟
SATA SSD 200-500 MiB/s 3-8 分钟
HDD 7200RPM 100-200 MiB/s 8-15 分钟
HDD 5400RPM 50-100 MiB/s 15-30 分钟

8.6 Scrub 与其他操作的关系

8.6.1 Scrub 与 Balance

操作 目的 对数据完整性的影响
Scrub 验证数据完整性 发现并修复损坏
Balance 重新分配空间 不验证完整性

💡 提示: 建议在 balance 之前先执行 scrub,确保数据完整性。

8.6.2 Scrub 与快照

# scrub 会校验所有数据,包括快照中的数据
# 快照与源子卷共享数据块,所以 scrub 高效地一次验证

8.6.3 Scrub 与 RAID

# RAID 1:scrub 自动修复损坏的副本
sudo btrfs scrub start /mnt/raid1
# 错误会被自动修复

# RAID 5/6:scrub 可以使用奇偶校验修复
# 但由于 write hole 问题,修复可能不完全可靠

8.7 本章小结

操作 命令
启动 scrub btrfs scrub start /mnt
等待完成 btrfs scrub start -B /mnt
查看状态 btrfs scrub status /mnt
取消 scrub btrfs scrub cancel /mnt
查看错误 btrfs scrub status -d /mnt
设备统计 btrfs device stats /mnt

关键要点

  1. Scrub 是发现静默数据损坏的唯一方法
  2. 生产环境建议每周执行 1-2 次
  3. RAID 模式下 scrub 可以自动修复损坏
  4. 使用 ionice/nice 降低 scrub 对业务的影响
  5. 配合告警脚本及时发现问题

扩展阅读