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

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/[email protected]
[Unit]
Description=Btrfs scrub timer for %i

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

[Install]
WantedBy=timers.target
# /etc/systemd/system/[email protected]
[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 [email protected]

# 检查定时器状态
sudo systemctl list-timers [email protected]

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:-[email protected]}"
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 SSD500-2000 MiB/s1-3 分钟
SATA SSD200-500 MiB/s3-8 分钟
HDD 7200RPM100-200 MiB/s8-15 分钟
HDD 5400RPM50-100 MiB/s15-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 本章小结

操作命令
启动 scrubbtrfs scrub start /mnt
等待完成btrfs scrub start -B /mnt
查看状态btrfs scrub status /mnt
取消 scrubbtrfs 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. 配合告警脚本及时发现问题

扩展阅读