Linux LVM thin provisioning 的 overcommit 与 snapshot 风险管理

1次阅读

thin pool用满后lvcreate不报错但写入失败,因thin provisioning存在overcommit风险,仅元数据分配不占物理空间,写入时可能eagain或hang;需监控data_percent、启用auto-extension、谨慎处理snapshot及metadata损坏风险。

Linux LVM thin provisioning 的 overcommit 与 snapshot 风险管理

thin pool 用满后 lvcreate 不报错但写入失败

Thin provisioning 的核心风险就是 overcommit:逻辑容量远超物理空间,lvcreate -T 创建 thin volume 时只分配元数据,不占实际空间。只要 thin pool 没满,命令就成功;但一写入就可能卡在 write() EAGAIN 或直接 hang 住——尤其对数据库、日志轮转这类持续写入场景。

实操建议:

  • 永远用 lvs -o+data_percent,metadata_percent 监控两个百分比,data_percent 超过 85% 就该预警
  • 启用 auto-extension:在 /etc/lvm/profile/thin_pool_activation.profile 中设 thin_pool_autoextend_threshold = 80thin_pool_autoextend_percent = 20,避免手动干预延迟
  • 别依赖 lvresize --poolmetadatasize 临时扩容 metadata,它不解决 data 空间不足,且 metadata 扩容本身有 I/O 开销

snapshot 占用空间不可见,lvs 显示 size 为 0

thin snapshot 不是传统 copy-on-write 那种独立 LV,而是共享同一 thin pool 的数据块引用。所以 lvs 里它的 LSize 是 0,但实际占用由“写入差异量”决定——改得越多,占用越大,且不会自动释放。

常见错误现象:

  • 创建 snapshot 后,data_percent 涨得飞快,但找不到哪个 LV 在写
  • lvconvert --merge 失败,报 Snapshot is busy,其实是 merge 过程中需要额外空间暂存新写入
  • 误删原 LV 后 snapshot 仍存在,但变成只读孤儿,继续吃 pool 空间

实操建议:

  • lvs -o+origin,lv_layout 区分 origin 和 snapshot,layout 字段显示 thinsnapshot
  • 定期清理不用的 snapshot:lvs | awk '/snapshot/ {print $1,$2}' | xargs -r -n2 sh -c 'lvremove -f $1/$2'
  • 不要对正在被 mount 或 open 的 LV 做 snapshot,否则可能触发 kernel 的 thin-pool lock 争用

thin pool 元数据损坏导致整个 VG 不可用

thin pool 的 metadata LV 是单点故障:它损坏,所有 thin volume(包括 snapshot)都会无法激活,vgchange -ayFailed to activate thin pool,甚至 vgs 都可能卡住。

原因很实在:metadata 默认用 1MB 缓存 + 无冗余存储,SSD 掉电、ext4 journal 错乱、LVM bug 都可能让它变脏。

实操建议:

  • 初始化 pool 时强制指定大一点的 metadata size:lvcreate -L 10G -T vg/pool -M y --poolmetadatasize 16M(默认常只有 2–4M)
  • 定期备份 metadata:thin_dump /dev/vg/pool_tmeta > /backup/pool_tmeta.dump.$(date +%F),出事时可用 thin_restore 回滚
  • 避免在 metadata LV 上做 fsck 或 dd,它不是普通文件系统,操作即高危

mysql InnoDB 在 thin LV 上因 discard 导致空间不回收

InnoDB 启用 innodb_file_per_table=ON + innodb_discard_threshold 后会主动 TRIM 删除的页,但 LVM thin 默认不透传 DISCARD 到底层设备——结果是 MySQL 认为空间已释放,LVM 却还记着那些块被占用,data_percent 居高不下。

实操建议:

  • 确认 thin pool 支持 discard:lvs -o+discards 输出应为 passdown,不是 ignore;若为 ignore,需重建 pool 并加 --discards passdown
  • 重建时注意顺序:先 lvconvert --thinpool --discards passdown vg/pool,再 lvcreate -T 新 volume
  • MySQL 侧配合:设 innodb_deadlock_detect=OFF 减少 thin-pool 元数据锁竞争(尤其高并发 delete 场景)

thin provisioning 的麻烦不在配置,而在空间账本是三套并行记的:应用层以为自己在管理文件大小,文件系统在管理 block 分配,LVM 在管理 extent 引用。哪一层没对齐,overcommit 就从便利变成事故。最常被忽略的是 metadata 容量和 discard 透传,这两个不提前设好,后面扩容、恢复、性能优化全要绕弯。

text=ZqhQzanResources