这是一起典型的企业级存储阵列"多盘接连失效"事故复盘。表面看是运气不好,实际是 SSD 超期服役、RAID 5 重构机制、运维流程三件事叠加的结果。全文按处置时间线展开,命令均已在同类环境实测。
先说结论:RAID 5 双盘失效时,盲目 Force Online 往往把最后一份能救的数据也污染了;老化 SSD 阵列强行跑 Rebuild,等于把降级卷拖进死锁。下面按实际处置顺序拆解。
一、事故现场
某核心业务节点的存储服务器告警,底层是 LSI/Broadcom MegaRAID 控制器,6 块 480GB SATA SSD 组 RAID 5,逻辑卷可用容量约 2.18TB。
storcli 查看物理盘状态:
storcli64 /c0/eall/sall show
Drive Status ErrCd ErrMsg
/c0/e8/s0 Success 0 -
/c0/e8/s1 Failure 46 -
/c0/e8/s2 Success 0 -
/c0/e8/s3 Success 0 -
/c0/e8/s4 Success 0 -
/c0/e8/s5 Failure 46 -
槽位状态展开看更清楚:
EID:Slt DID State DG Size Intf Med Model
8:0 9 Onln 0 446.625 GB SATA SSD Micron_5100
8:1 12 Failed 0 446.625 GB SATA SSD -
8:2 10 Onln 0 446.625 GB SATA SSD Micron_5100
8:3 14 Onln 0 446.625 GB SATA SSD Micron_5100
8:4 11 Onln 0 446.625 GB SATA SSD Micron_5100
8:5 13 UBad - 446.625 GB SATA SSD -
Slot 1 是 Failed,Slot 5 是 UBad(未配置的坏盘)。RAID 5 只能容忍一块坏盘,两块同时掉线,整个 VD 0 直接 Offline。
二、第一步:查 SEL 日志定"先掉线的是谁"
这里是整个处置里最关键、也最容易做错的一步。
RAID 5 双盘失效后,阵列上留下的数据是"混合"状态:先掉线的那块盘数据是陈旧的,后掉线的那块盘才承载崩溃前的最新数据。如果把陈旧盘强制拉回上线,它的旧数据块会参与 XOR 校验,写回去就是数据污染。
判断依据在 BMC 的硬件事件日志里。通过 IPMI 导出 SEL:
ipmitool sel elist | grep -i drive
输出示例:
04/10/2026 | 01:42:49 | Drive Slot DISK5_Status | Drive Fault | Asserted
08/16/2026 | 03:59:15 | Drive Slot DISK1_Status | Drive Fault | Asserted
时间线一目了然:Slot 5 在 4 月就坏了,服务器带伤跑了 4 个多月;Slot 1 是 8 月 16 日凌晨挂的,是压垮阵列的最后一根稻草。
决策:强制拉回 Slot 1,绝对不碰 Slot 5。
三、第二步:拉回 Slot 1,换盘启动 Rebuild
进 Linux 救援系统(建议用救援系统或 Live 环境,不要在生产系统上动阵列):
# 强制把 Slot 1 拉回上线
storcli64 /c0/e8/s1 set online
# 确认 VD 状态
storcli64 /c0/vall showVirtual Drives
VD 0 从 Offline 恢复到 Dgrd(Degraded),逻辑卷可读:
lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:32 0 2.2T 0 disk
├─sda1 8:33 0 450M 0 part
├─sda2 8:34 0 100M 0 part
├─sda3 8:35 0 16M 0 part
├─sda4 8:36 0 150G 0 part
└─sda5 8:37 0 2T 0 part
然后拔出物理损坏的 Slot 5,换上新盘,导入并启动重构:
storcli64 /c0/e8/s5 insert dg=0 array=0 row=5
storcli64 /c0/e8/s5 start rebuild
storcli64 /c0/e8/s5 show rebuild
# Drive-ID Progress% Status Estimated Time Left
# /c0/e8/s5 0 In progress 3 Hours 1 Minutes
到这里看起来流程很标准。但真正的麻烦才开始。
四、连环故障:重构在 0.8% 处崩掉
重构刚跑起来,进度不到 0.8%,VD 再次 Offline。
storcli64 /c0/e8/s1 show all | grep -E "Media Error Count|Other Error Count"
# Media Error Count = 1
# Other Error Count = 42
事件日志给出了决定性线索:
Event Description: Unexpected sense: PD 0c(e0x08/s1), CDB: 28 00 00 7b 7c 91 00 00 6f 00, Sense: 6/29/00
Event Description: PD 0c(e0x08/s1) reset (Type 03)
Event Description: Rebuild failed on PD 0d(e0x08/s5) due to source drive error
Event Description: VD 00/0 is now OFFLINE
内核层面同步刷屏:
[ 3162.434076] megaraid_sas 0000:5e:00.0: 59530 - Unrecoverable medium error during recovery on PD 0c(e0x08/s1) at 7b7c90
翻译一下:Slot 1 在物理扇区 0x007B7C91(LBA 8092817,约 4.14GB 处)有物理坏块。全盘连续读扫到这一块就超时,控制器下发 Reset Type 03 并把它隔离(CFShld,配置保护隔离)。
解除隔离并重新导入
# 先把 Slot 5 拔掉,避免它自动触发重构进入死循环
storcli64 /c0/e8/s1 set good force
storcli64 /c0/fall import
VD 0 恢复到 Dgrd,逻辑卷可读。
关键手法:写零触发 SSD 主控重映射
这是本次处置里最有价值的一个知识点。
SSD 的物理机制决定了:弱扇区只有在被写入时,主控才会判定其为坏块并把它重映射到备用闪存区。纯读取只是暴露问题,写入才是"修复"动作。
先看底层证据。smartctl 直通阵列卡读取物理盘 SMART:
smartctl -d megaraid,12 -a /dev/sda | grep -E -i "id#|realloc|pending|uncorrect"
# 5 Reallocated_Sector_Ct 0x0032 100 100 001 Old_age Always - 3187
# 187 Reported_Uncorrect 0x0032 100 100 000 Old_age Always - 9196
# 188 Reallocated_Event_Count 0x0032 100 100 000 Old_age Always - 3
错误日志精确记录了坏块位置:
# Error: UNC at LBA = 0x007b7c91 = 8092817
# Error: UNC at LBA = 0x007b7c80 = 8092800
# Error: UNC at LBA = 0x007b7c90 = 8092816
先测读取速度确认劣化程度:
dd if=/dev/sda of=/dev/null bs=64k skip=300000 count=40000 iflag=direct status=progress
# 1056571392 bytes (1.1 GB, 1008 MiB) copied, 452 s, 2.3 MB/s
2.3 MB/s——这块盘基本读不动了。而对应的写入区段走一遍零填充:
dd if=/dev/zero of=/dev/sda bs=1M seek=19500 count=1500 oflag=direct status=progress
# 1500+0 records in / 1500+0 records out
# 1572864000 bytes (1.6 GB, 1.5 GiB) copied, 3.53744 s, 445 MB/s
再回读验证,速度已恢复到 324 MB/s:
dd if=/dev/sda of=/dev/null bs=1M skip=19500 count=1500 iflag=direct status=progress
# 1572864000 bytes (1.6 GB, 1.5 GiB) copied, 4.85497 s, 324 MB/s
写零成功触发主控重映射,坏块问题暂时排除。
⚠️ 风险提示:dd oflag=direct 直写裸设备会直接覆盖原数据。此处能这么做,前提是这块盘的对应区段已经被 RAID 冗余保护、或该区段数据已确认无价值。在没有冗余保护的单盘上执行,等于销毁数据。务必先确认。
五、二度触礁:Slot 2 在 51.88% 处崩溃
插回 Slot 5 重启 Rebuild,这次前 50% 跑得顺畅。到了 51.88%,VD 再次 Offline。
storcli64 /c0/v0 showVirtual Drives
# 0/0 RAID5 OfLn RW No RWBD - ON 2.180 TB
storcli64 /c0/e8/s2 showDrive Information
# 8:2 10 UBad - 446.625 GB SATA SSD -
同样的剧本,坏在另一个盘上:
Event Description: Unexpected sense: PD 0a(e0x08/s2), CDB: 28 00 1d 00 2d 11 00 00 6f 00, Sense: 6/29/00
Event Description: PD 0a(e0x08/s2) reset (Type 03)
Event Description: Rebuild failed on PD 0d(e0x08/s5) due to source drive error
CDB 里 1d 00 2d 11 对应物理扇区 0x1D002D11(LBA 486550801,约 249.1GB 处)读超时。老规矩处理:
storcli64 /c0/e8/s2 set good force
storcli64 /c0/fall import
dd if=/dev/zero of=/dev/sda bs=64k seek=19004000 count=4000 conv=notrunc oflag=direct
dd if=/dev/sda of=/dev/null bs=64k skip=19004000 count=4000 iflag=direct status=progress
Slot 2 稳住了。但第二次修到 51.88% 才出问题,这已经不是局部故障了——后面 48% 的未扫区间里大概率还埋着弱扇区。
六、战术调整:绕开 Rebuild,改在 Linux 层主动预读排雷
教训很清晰:MegaRAID 的 Rebuild 只要掉一次盘,进度就归零。插着 Slot 5 跑重构就是"跑一半→掉盘→归零"的无限循环,代价是时间和风险成倍放大。
换打法:把 Slot 5 拔下来,不挂 Rebuild,直接在 Linux 层对逻辑卷做全盘主动预读扫描,提前把暗礁标出来。好处是扫描过程中不需要承受进度归零的代价。
dd if=/dev/sda of=/dev/null bs=1M skip=1200000 iflag=direct status=progress
# 99575922688 bytes (100 GB, 93 GiB) copied, 560 s, 178 MB/s
# dd: error reading '/dev/sda': Input/output error
# 95137+0 records in / 95137+0 records out
在 1295137 MB(约 1.295TB,54% 深度)处精准拦下下一颗暗礁。DD 以 MB 为单位,定位时注意换算:
# 1295137 MB ≈ 1264.78 GB ≈ 1.264 TB
直接在线修复这一小段:
storcli64 /c0/e8/s2 set online
storcli64 /c0/v0 showVirtual Drives # 确认回到 Dgrd
dd if=/dev/zero of=/dev/sda bs=1M seek=1295130 count=20 conv=notrunc oflag=direct
dd if=/dev/sda of=/dev/null bs=1M seek=1295130 count=20 iflag=direct status=progress
写零后继续往后扫,一路推进到 1.434TB(约 62.7% 深度)暂时安全:
dd if=/dev/sda of=/dev/null bs=1M skip=1295150 iflag=direct status=progress
# 139230969856 bytes (139 GB, 130 GiB) copied, 877 s, 159 MB/s
然后提速冲关,把控制器重构速率提到 60%,重新插上 Slot 5:
storcli64 /c0 set rebuildrate=60
storcli64 /c0/e8/s5 insert dg=0 array=0 row=5
storcli64 /c0/e8/s5 start rebuild
storcli64 /c0/e8/s5 show rebuild
# /c0/e8/s5 0 In progress 2 Hours 18 Minutes
结果重构推进到后半段未扫区间时,Slot 2 再次因未知弱扇区读超时掉线:
storcli64 /c0/eall/sall show
# /c0/e8/s2 Failure 46 -
三次修盘、三次掉线。到这一步基本可以判定:这不是局部故障,是整批盘的寿命走到了尽头。
七、终局:SMART 体检单
批量穿透 MegaRAID 抓取所有物理盘的 SMART:
for did in 9 12 10 14 11; do
echo "==================== [ MegaRAID DID: $did ] ===================="
smartctl -d megaraid,$did -i -A /dev/sdc |
grep -E -i "Device Model|Serial Number|Power_On_Hours|Reallocated_Sector_Ct|Reported_Uncorrect|Unused_Rsvd_Blk_Cnt"
done
输出节选:
==================== [ MegaRAID DID: 9 / Slot 0 ] ====================
Device Model: Micron_5100_MTFDDAK480TBY
Serial Number: 18011A7855F5
5 Reallocated_Sector_Ct 0x0032 100 100 001 Old_age Always - 3187
9 Power_On_Hours 0x0032 100 100 001 Old_age Always - 74726
187 Reported_Uncorrect 0x0032 100 100 000 Old_age Always - 9196
180 Unused_Rsvd_Blk_Cnt_Tot 0x0033 000 000 000 Pre-fail Always - 5656
==================== [ MegaRAID DID: 12 / Slot 1 ] ====================
Device Model: Micron_5100_MTFDDAK480TBY
Serial Number: 18011A7868W1
9 Power_On_Hours 0x0032 100 100 001 Old_age Always - 74722
187 Reported_Uncorrect 0x0032 100 100 000 Old_age Always - 12367
数据摆在面前:
通电 74726 小时,折合 8.53 年(3113 天)连续 7×24 运转,超期服役约 170%。企业级 SATA SSD 的设计寿命通常是 3 到 5 年,这批盘已经严重透支。Slot 1 的 Reported_Uncorrect 高达 12367 次。
死因链路很清晰:
- NAND 闪存的绝缘氧化层结构性磨损,电荷保持能力枯竭
- 底层 LDPC/ECC 纠错引擎面对弥散性比特翻转无能为力
- 介质衰竭导致重构死锁
- RAID 5 重构要求对所有存活盘做 100% 满负荷深度连续读取,老化盘主控在深层纠错时陷入死锁、触发总线复位
- 强行 Rebuild 只会引发多盘同时暴毙
八、最终处置:降级只读导出数据
放弃强行重构。把 Slot 2 拉回上线,让阵列保持 Degraded 状态,以只读方式挂载业务分区:
storcli64 /c0/e8/s2 set online
mount -o ro,norecover /dev/sdc5 /mnt/backup
norecover 是关键:告诉文件系统不要尝试写日志和回放 journal,纯读挂载。
然后 rsync 导出核心业务数据:
rsync -aHAX --info=progress2 /mnt/backup/data/ /backup/data/
为什么只读拷贝是唯一生路?业务文件系统通常只占用了卷的一部分空间,只读挂载只会读取已分配的簇,天然避开未分配空间里的大量坏块,能安全把核心数据同步出来。而 Rebuild 要求 100% 深度扫描,会把那些坏块全部踩一遍。
九、四条可复用的铁律
一、双盘失效别慌,查 SEL 日志选最新的那块强制上线。
切勿盲目 Force Online。务必通过 IPMI/SEL 核对时间戳,只上线最后掉线的那块盘。拉错一块,全盘数据污染。
二、老化 SSD 阵列,严禁强行跑 Rebuild。
重构要求全盘 100% 深度连续读。寿命临界点的老盘,这种读取会引发连续超时掉盘,把原本可挽救的降级卷彻底拖入死锁。宁可先只读导出数据,再离线重建。
三、SS 弱扇区的修复手段是"写零"而不是"读一遍"。
SSD 只有在写入时才判定坏块并重映射。读只暴露问题,写才修复。但写零前必须确认该区段有冗余保护或数据无价值。
四、同一批次的硬件要防"集体雪崩",监控红线前移到 SMART。
同工况运行 8.5 年的 SSD,寿命消耗高度一致——一块出问题,往往意味着整批都到点了。日常巡检必须盯紧 Power_On_Hours(建议超过 4 万小时就规划轮换)和 Reported_Uncorrect,在介质彻底衰竭前完成迁移,而不是等告警。
附:巡检清单
把上面的经验落成日常巡检项:
# 1. 全局 SMART 体检(穿透 RAID 卡)
for did in $(seq 9 14); do
smartctl -d megaraid,$did -i -A /dev/sdc |
grep -E "Power_On_Hours|Reported_Uncorrect|Unused_Rsvd_Blk_Cnt"
done
# 2. 阵列健康度
storcli64 /c0/vall showVirtual Drives
storcli64 /c0/eall/sall show
# 3. BMC 硬件事件(看有没有新的 Drive Fault)
ipmitool sel elist | grep -i drive
# 4. 底层内核错误
dmesg -T | grep -iE "megaraid|medium error|I/O error"
# 5. 单盘直通核对
smartctl -d megaraid,12 -a /dev/sda
巡检节奏建议:
- 每日:storcli 阵列状态 + BMC SEL 增量
- 每周:全盘 SMART 抓取,重点看 Power_On_Hours 与 Reported_Uncorrect 趋势
- 每月:随机抽 1-2 块盘做
smartctl -t自检 - 阈值线:通电 4 万小时或 Reported_Uncorrect 持续增长 → 提前进入更换计划
结语
这次事故真正的教训不在 RAID 5,而在于资产管理。硬件有寿命,SMART 里有答案,但它不会主动举手——你得定期去看。存储阵列上的数据再重要,也重要不过在它彻底躺下之前完成一次有序的迁移。
本文技术方法与命令为笔者整理并实测验证。案例原型参考自技术社区公开文章《通电 74,726 小时的企业级 SSD 暴毙记》(公众号「Linux客栈」),在此致谢并推荐阅读原文:https://mp.weixin.qq.com/s/LwxQGjlQkrd52w_R8k7-1A。本文为原创整理与扩展,转载请注明出处。
文章评论