开头
先说结论:PV missing 这种故障,绝大多数情况下不是 LVM 本身坏了,而是它依赖的底层设备在“内核视角”里消失了。换句话说,LVM 只是记住了“某个物理卷曾经在某个设备上”,当它再次扫描时发现那个设备不见了,就标记成 missing。搞清楚这个逻辑,后面所有排查动作都会顺很多。
事故发生在我负责的一套数据库主机上。那天凌晨监控先报磁盘IO错误,紧接着 LVM 告警跟过来,内容是 VG 状态异常。我登录上去执行pvs,看到其中一行 PV 列不再是/dev/sdb1这样的路径,而是[unknown],挂载点对应的 LV 也进入了无法正常访问的状态。第一反应不是慌着去强制激活,而是先确认底层磁盘到底还在不在。这篇记录我就按当时的排查链路展开,从现象确认到根因定位,再到应急处理和事后预防,把思路和命令都写清楚,希望对遇到类似问题的朋友有帮助。凡是涉及环境的细节我都做了模糊化处理,重点看排查逻辑,不用纠结具体型号和路径。
1. 故障表象与初步确认:missing 到底是哪种"丢"
1.1 现场第一步:先把状态读全
遇到任何 LVM 异常,我的习惯是先执行一轮只读命令把全貌拉出来,不要急着操作。命令就三个,输出不会骗人:
pvs vgs lvs当时pvs的输出里,有一行长这样:
PV VG Fmt Attr PSize PFree /dev/sda2 vg0 lvm2 a-- 100.00g 20.00g [unknown] vg0 lvm2 a-m 500.00g 0.00g注意第二行的 Attr 列里有个m,这个字符就是 missing 的缩写。vgs里对应 VG 的 Attr 也可能带m,比如z--变成z-m。lvs里能看到受影响的 LV 状态不再完全是-a-,有的会变成-a-m,甚至某些 LV 会直接显示为unknown device。
这三条命令看完,基本可以确认:丢失的是一个包含 500G 容量的 PV,而这个 PV 上承载的 LV 很可能就是数据库数据目录。此时系统里如果还有应用在写入,大概率已经报出"设备上没有剩余空间"或者"输入输出错误",因为逻辑卷对应的完整设备已经不在了。
1.2 missing 不等于文件丢了
很多第一次遇到这个问题的同学会误以为"PV missing 就是数据全没了",其实不是。LVM 对物理卷的管理分两层:一是设备本身,二是设备上记录的 LVM 元数据。missing表示 LVM 在扫描设备时找不到那台设备了,但只要设备重新出现且元数据完好,整个 VG 就能恢复原状。这有点像你的记事本上记了"东西放在保险柜第三格",现在保险柜暂时打不开,你不能说记事本记录就没意义了。
所以要给这次故障定个性:当前不是"数据损坏",而是"设备不可见"。接下来的所有排查,都要围绕"为什么内核看不到这块盘"展开。我会在下一节按从下往上的顺序逐层排查:先看内核,再看系统设备映射,再看多路径,最后回到 LVM。
1.3 确认受影响范围,决定是否需要立刻停机
在动手之前还有一个关键动作:评估业务影响面。df -h只能看到已挂载文件系统,看不到 LVM 层完整视图,所以我推荐结合dmsetup ls和/proc/mounts一起看:
dmsetup ls | grep vg0 grep vg0 /proc/mounts如果受影响的 LV 有文件系统且已挂载,先确认还有没有进程在使用它,可以用fuser -v /挂载点或者lsof +d /挂载点。如果没有任何进程占用,那可以相对从容地慢慢排查;如果有数据库在持续写入,就需要准备业务切换或者临时停写,避免在底层设备不稳的情况下继续读写,把本就脆弱的状态进一步搞复杂。
这一步直接决定你后面是“从容查链路”还是“紧急恢复”,千万别跳过。我当时查下来,数据库实例因为 IO 错误已经自己把写入停了,所以后面有很多操作窗口,这也是我敢反复扫描设备而没有立刻重启的原因之一。
2. 逐层排查:从内核视角到磁盘链路再到多路径映射
2.1 第一层:dmesg 里通常已经有答案的雏形
进入深度排查,第一个要看的是内核日志,因为它记录了磁盘从“正常”到“消失”的完整过程。执行:
dmesg -T | grep -E "sd[b-z]|I/O error|link down|host reset|end_device" | tail -100我这边输出的关键行和解读如下:
[日期 时间] sd 0:2:0:1: [sdb] tag#42 FAILED [日期 时间] blk_update_request: I/O error, dev sdb, sector 2048 [日期 时间] sd 0:2:0:1: [sdb] Synchronize Cache(10) failed: SMARTPORT: status = 0x3sector 2048这个偏移很有信息量,因为标准的 LVM 物理卷标签就写在设备起始位置往后约 1 MiB 的区域内,也就是 2048 扇区附近。这说明 IO 错误直接落在了 LVM 元数据所在的位置,导致 LVM 无法读取该 PV 的头部信息。内核层面这台设备已经处于不可用状态,/dev/sdb这个节点虽然可能还在,但发出去的 IO 全部失败。
如果 dmesg 里完全没有 SCSI 错误,而是只有类似sdb: Spinning up disk...或sdb: READ CAPACITY failed的提示,那更偏向于磁盘固件或盘体故障;如果 dmesg 里干净得像没事一样,但设备就是不在lsblk里,那大概率是多路径或者设备映射层面的问题,要继续往上层查。
2.2 第二层:内核到底认不认这块盘
接下来用两个命令确认内核是否还能看到该设备:
lsblk cat /proc/partitions正常情况下,如果丢失的 PV 原本是/dev/sdb1,那么/dev/sdb应该出现在lsblk中,并且分区表里能看到/dev/sdb1。当时我执行后显示整个sdb都不存在了,/proc/partitions里也没有对应主设备号 8 的 sdb。这说明问题已经超出了 LVM 层面,是底层存储设备在内核里消失了。
这种情况常见的候选原因有几个:SAS/SATA 线缆松动或背板接触不良、硬盘休眠后无法唤醒、HBA 卡驱动异常导致设备被移除,或者 RAID 卡 / 直通卡把后端磁盘和控制器之间的连接断开了。如果是多路径环境,还要考虑一条路径失联后 Multipath 是否已经把设备整体置为 failed。
如果lsblk能看到设备块,只是分区不见了,那反而简单一些,属于分区表或设备节点问题,后续可以用partprobe或kpartx重新读取。最麻烦的是这种“整个设备从内核消失”的情况,因为 LVM 无论怎么扫描都无法凭空找到它。
2.3 第三层:多路径设备的特殊性
如果你用了 Device Mapper Multipath(常见于存储阵列环境),那么 LVM 看到的 PV 路径往往是/dev/mapper/xxxx这一类。此时 sdb、sdc 这样的物理设备其实只是底层路径,真正的可用户设备是 multipath 映射出来的那块。
遇到 PV missing 且底层物理盘都在时,第一件事要看:
multipath -ll关注有没有 WWID 相同的设备只出现了一条路径,或者某个 map 的 status 变成failed、defective、undef。如果物理路径都在而 map 状态不对,可以尝试:
multipath -r重新加载多路径配置。注意这个过程会让该 map 下的 IO 短暂中断,生产环境要挑业务低峰或跟应用确认后再做。如果multipath -ll里直接把某个 map 丢掉了,那要检查/etc/multipath.conf里的 WWID 匹配规则是否正确,以及multipathd服务是否因为配置重载把设备给过滤掉了。当时我这台设备没有走多路径,是单机直连 JBOD 磁盘,所以这一层基本可以跳过,但排查思路要记录在案,方便读者对号入座。
2.4 回到 LVM 层:pvscan 到底在扫描什么
确认底层无望后,我回到 LVM 侧执行了:
pvscan输出里依然显示那个 PV 为 missing。这里解释一个原理:pvscan是扫描系统里的所有块设备,读取设备头部是否有 LVM 标签和元数据。如果设备不存在,那么扫描结果自然不会包含该 PV,于是 LVM 只能依赖缓存在 VG 元数据里的旧记录,将对应 PV 标为 missing。这个机制也解释了为什么pvscan --cache在某些临时性设备消失的场景能“让 PV 重新出现”,其实它只是强制更新了内核里的设备映射缓存,并不能修复硬件问题。
此时不要反复重启机器来试图“找回”磁盘。重启确实可能因为重新初始化 HBA 让盘重新识别,但如果存在硬件隐患,重启后盘可能在开机过程中再次掉线,反而让系统进入更复杂的状态。更稳妥的做法是在线重扫 SCSI 总线或重新探测指定控制器。
3. 根因定位与恢复方案:三种常见情况和对应操作
3.1 情况A:盘体物理故障,确认槽位与硬件状态
如果 dmesg 里大量出现FAILED、Synchronize Cache failed、Unrecovered read error,而且smartctl已经无法正常读取盘的信息,那基本可以下结论是盘体故障。此时要做的不是去幻想通过软件恢复,而是:
- 确认磁盘对应物理槽位。通过
lsscsi --verbose查看设备的 scsi 地址,进一步对应到机箱编号。 - 更换新盘。如果是 RAID 卡下的热备盘,控制卡会自动开始重建;如果是不在 RAID 里直接以 JBOD 方式接入的盘,则需要手动处理。
- 新盘插上后,先确认内核识别正常(再次用
lsblk),然后pvcreate /dev/sdb1是需要非常谨慎的操作,要求新盘能完整承载原 PV 上的数据才有意义。
这里面最关键的经验是:不要见到 missing 就立刻vgreduce --removemissing。如果盘还能被识别但 IO 不稳定,优先做镜像或迁移到新盘;只有在确认盘彻底废掉且数据可以从备份或其他副本恢复的情况下,才允许移除 PV。我在多次应急里见过最亏的操作就是把还活着的盘踢出 VG,导致后续无法恢复。
3.2 情况B:路径或设备名变化导致 LVM 找不到 PV
另一种常见场景:盘没坏,但是设备路径变了。例如原来/dev/sdb1因为启动时检测顺序变化变成了/dev/sdc1,LVM 按路径找旧 PV 自然找不到。在非多路径的单机环境里,这通常发生在加了新盘、换了 HBA 卡、或者内核版本升级之后。
要确认是不是这种场景,可以执行:
blkid | grep -i lvm如果能看到某个已经挂到新路径的设备带有LVM2_member的 PARTUUID 或 UUID,那么真相大白。此时不需要重建 PV,只需要让 LVM 重新识别新路径即可:
pvscan --cache这个命令会让 LVM 重新扫描所有块设备并更新缓存。如果还不生效,可以再执行:
vgscan --mknodes vgchange -a y vg0上面两个命令一个是重新生成设备节点,一个是重新激活 VG。在执行激活操作前,务必确认没有其他主机在同时访问该存储(尤其共享存储环境),否则存在数据不一致风险。
3.3 情况C:元数据损坏或顺序紊乱,用 vgcfgrestore 兜底
最麻烦的第三种情况是设备在、PV 也在,但 LVM 元数据损坏或者说 vg 内部记录的 PV 顺序和实际不一致。这类问题常见于意外断电、强制拔盘或者有第三方软件错误写入导致的元数据错乱。此时先看备份:
ls /etc/lvm/archive/LVM 默认会在 VG 配置变更时自动归档旧配置,在/etc/lvm/archive/下保留若干份历史版本。用vgcfgrestore --list vg0可以查看可恢复的历史时间点。恢复流程是先vgchange -a n vg0让 VG 处于非激活状态,然后vgcfgrestore vg0 -f /etc/lvm/archive/vg0_xxx.vg恢复到某个可信版本,最后再vgchange -a y vg0激活。
但要提醒一点:vgcfgrestore恢复的是 VG 元数据,不涉及 PE 内部的数据内容。如果文件系统本身已经损坏,恢复元数据并不能解决文件系统层面问题。基础判断方法是在 PV 重新可见后,用fsck -n对逻辑卷做只读检查,确认文件系统是否健康,再决定是否写操作。
3.4 这次故障的实际根因
这次实际排查下来,最后定位到的情况是:磁盘并没有物理损坏,而是因为存储底层发生了一次短暂链路抖动,导致盘从内核里被移除,同时系统里的设备节点没有重新生成。按照上述情况B的处理思路,重新扫描 SCSI 总线后盘重新出现,再执行pvscan --cache,LVM 就恢复了正常状态,LV 也能自动重新挂载。整个过程没有丢 PE,也没有重做 PV。这也再次验证了一个理念:PV missing 未必等于数据灾难,先把链路找回来再说。
4. 应急处理:missing 状态下如何保住可用性
4.1 不要盲目重启,也不要直接删 PV
先说反例。我见过不少同行在处理 PV missing 时选择了直接重启机器,期望盘能重新出现。如果仅仅是为了重新识别设备,重启的成本太高且风险不可控,因为:
- 重启过程会触发修复或 fsck,如果文件系统本身有问题,可能扩大损伤。
- 一些存储链路问题在重启后依然存在,等于白等。
- 如果是数据库环境,重启意味着长时间不可用,不如在线处理。
同样不要急着执行vgreduce --removemissing。这个命令的本质是把丢失的 PV 从 VG 里移除,这意味着 VG 的元数据将不再包含该 PV,之后即使盘重新出现,也需要通过vgextend把它加回来,而原本 PV 上的数据在 LVM 看来就成了未分配的新空间。如果那块盘其实还能读,直接移除会让恢复变的非常被动。
4.2 尝试在线重扫,给系统一次“重新发现”的机会
在打开机箱或联系硬件厂商前,有一个低成本动作值得先做:重扫 SCSI 总线。假设设备原本是 host0 下的 2:0:1,可以这样操作:
echo "- - -" > /sys/class/scsi_host/host0/scan如果不知道具体是哪个 host,先看:
ls /sys/class/scsi_host/逐个对每个 host 执行重扫,或者写个循环。注意该操作属于在线修改内核设备状态,生产环境操作前最好先确认没有正在进行的备份或大文件传输。执行后再次lsblk,往往能看到设备重新出现。
如果盘重新出现后 LVM 还是没有恢复,再执行:
pvscan --cache --activate vg这样能够强制刷新 LVM 的设备映射缓存并尝试重新激活 VG。对多数链路抖动引起的 missing,这两步组合拳已经足够。
4.3 只读挂载临时捞数据
如果受影响的 LV 上数据非常重要,而且盘暂时回不来,可以考虑通过只读方式访问。做法是:先把该 LV 激活为不可读写状态,然后用文件系统的只读选项挂载。以 ext4 为例:
vgchange -a n vg0 vgchange -a y vg0 --partial mount -o ro,noload /dev/vg0/lv_data /mnt/recovery--partial参数允许在部分 PV 缺失的情况下尝试激活 VG。noload选项对 ext4 很关键,它跳过日志回放,能够避免写入操作。只读挂载的目的不是修复,而是尽可能把还能看到的数据复制出来。注意,这种方法能成功的前提是缺失 PV 上的数据不构成 LV 的元数据核心区,否则 LV 根本无法激活。
4.4 备份优先,数据恢复永远比系统恢复重要
在整个应急过程中,我的优先级判断是这样的:先保证不丢数据,再保证业务可恢复,最后才考虑系统干净不干净。如果在 missing 状态下还能捞数据,那就第一时间备份;如果盘还在但 IO 不稳,那就先尝试做镜像或快照;如果盘彻底没希望,那就走替代路径,比如从备份恢复。不要为了“让系统看起来正常”而牺牲数据完整性,这是这条故障处理线里最重要的一条经验。
5. 事后复盘:为什么 PV 会 missing,以及怎么预防
5.1 根因分类:硬件、链路、配置、人为
吃一次教训就值得把这一类问题梳理成清单。根据我见过的案例,PV missing 的根因可以分为四大类:
| 类型 | 典型表现 | 排查方向 | 预防手段 |
|---|---|---|---|
| 硬件损坏 | dmesg 大量 IO 错误,smartctl 异常 | 盘体、RAID 卡、背板、电源 | 监控 smart 状态、定期巡检 |
| 链路抖动 | dmesg 有 link reset,短暂掉线后恢复 | 线缆、HBA、多路径配置 | 双路径冗余、紧固线缆 |
| 配置变更 | 设备路径变化、分区表丢失 | 检查设备命名方式、udev 规则 | 使用 by-id/by-uuid 方式引用设备 |
| 人为误操作 | 手滑把盘拔了或误删分区 | 操作审计、变更记录 | 变更审批、操作复核 |
这张表里的内容是这些年在生产环境反复踩过的坑,列出来不是为了吓唬人,而是要说明:PV missing 是一个结果,不是原因。每次处理完后,最该问的是“底层为什么不见了”这个为什么,而不是“怎么把它加回来”这个怎么办。
5.2 监控与巡检:从"事后救火"到"事前发现"
很多 PV missing 在演变成业务中断前,其实是有信号可循的。比如磁盘在消失之前可能有段时间持续出现 IO 错误,或者dmesg里已经有过一次 link reset。如果监控缺失,这些信号就被淹没了。
我的建议是在所有 LVM 环境里配置两个层次的监控:
- 第一层是硬件健康监控。至少要把 smartctl 的
SMART error log和Pending sector count纳入告警;对支持 SNMP 的存储,监控控制器事件日志。 - 第二层是 LVM 状态监控。最简单的方式是定时执行
vgs并检查 VG Attr 里有没有m标记,或者用lvs -o +devices持续观察设备映射是否异常。可以把这些检查写成一个脚本,放在定时任务里,一旦发现 missing 立刻告警。
这层监控最大的价值是让你在 PV 真正 missing 之前就接到预警,而不是凌晨被数据库故障叫醒。
5.3 用 UUID 和 Multipath 减少设备名漂移
另一个重要的预防方向是去掉对/dev/sdX这类不稳定路径的依赖。LVM 本身的机制是支持通过 UUID 识别 PV 的,默认pvscan会读取设备号的 UUID,所以通常不会因为路径漂移而丢失 PV。但问题是,如果你的启动脚本、fstab、或者手动执行的命令里用了硬编码的 sd 设备路径,一旦设备名漂移,问题就会从“找不到盘”变成“挂载错盘”甚至“挂载到错误数据”。
推荐做法是:
- 在
/etc/fstab中使用/dev/mapper/路径或UUID=方式挂载文件系统。 - 多路径环境统一使用
/dev/mapper/mpathX或 WWID 别名,避免直接引用底层物理盘。 - LVM 建 PV 时直接用完整设备路径而非短路径,例如
/dev/sdb1与/dev/sdb在 LVM 看来含义不同,容易在脚本里混淆。
另外,如果环境里存在多个磁盘且没有 RAID 卡管理,给每个物理盘贴标签并记录序列号和槽位关系会非常有用。故障时能快速区分是盘坏了还是识别顺序变了。这一点对日常运维帮助很大,别嫌麻烦。
5.4 常态化演练:在故障发生前先模拟一次
最后想多说一句:PV missing 这类故障,最好的学习方式不是看文档,而是自己在测试环境里模拟一遍。可以找一台闲置机器,建一个 VG,准备一个 PV,然后故意拔掉一块盘(或者在虚拟机里 detach 一块虚拟磁盘),重现 missing 状态,再按照本文描述的流程逐步恢复。整个过程做一次,你对 LVM 元数据的理解会深很多,真出事时也不会手忙脚乱。我在处理完这次故障后,就用虚拟机做了一次完全相同的演练,把命令执行顺序和输出记在了自己的运维手册里。后续如果再遇到类似告警,心里就有谱了。
结尾
这条故障处理下来,给我最深的一个体会是:PV missing 表面上是 LVM 的问题,骨子里却是“设备可见性”的问题。排查时不要盯着 LVM 本身去看,而是顺着存储链路往下查,从 dmesg 到 lsblk 再到 multipath,一层层确认问题出在哪,再决定用什么手段恢复。盲目的重启、盲目的 vgreduce、盲目的 pvcreate,都可能让一个小问题变成数据事故。如果你也遇到了类似情况,建议先把状态读全、评估影响、再逐层排查。只要盘还在、元数据还在,恢复路径通常都在;就算盘真的没了,提前做过的备份和监控也会让你有足够的余地处理。
最后分享一个小技巧:日常巡检时,记得看一下/etc/lvm/backup/目录下的 VG 备份文件时间戳是否够新。LVM 每次配置变更都会自动备份,但如果你太久没有做过变更,备份可能停留在很早以前。建议定期手动执行一次vgcfgbackup,并把备份文件同步到独立位置。这个习惯成本很低,但真到需要vgcfgrestore的时候,它就是救命稻草。