virsh snapshot-delete 仅删除快照元数据及未被引用的增量文件,不触发在线合并;真正合并差量必须关机后使用 qemu-img commit 手动 flatten 链。

virsh 不能在线合并快照差量层 —— 这是关键前提。KVM/libvirt 的 virsh snapshot-delete 仅删除快照元数据和对应增量文件(如 vmname-snap-xxx.qcow2),但不会触发“活跃层 → 父层”的实时合并;它只在后续写入或关机时由 QEMU 自动惰性合并,且仅限于被删除快照的子快照存在时才可能回收空间。
virsh snapshot-delete 删除快照的实际行为
执行 virsh snapshot-delete vmname snapname 后:
- 该快照从
virsh snapshot-list中消失,其 XML 描述、qcow2 增量文件(若未被其他快照引用)会被移除 - 如果该快照是链中中间节点(比如快照 A → B → C,你删 B),B 的数据仍需保留供 C 使用,此时
snapshot-delete不会删物理数据,也不会立即释放磁盘空间 - 只有当被删快照是“叶子节点”(无子快照),且其增量内容未被任何现存快照引用时,对应 qcow2 文件才会被真正删除
- 不关机、不重启虚拟机,QEMU 不会主动把活跃层(current layer)的数据回写到父镜像 —— 所以不存在“在线合并”这回事
想真正合并差量?必须关机 + 手动 flatten
要让所有差量写回基础镜像(即彻底 flatten 链),唯一可靠方式是:
- 先确保虚拟机已关机:
virsh shutdown vmname(或virsh destroy vmname强制终止) - 确认当前活动快照是你要保留的终点(用
virsh snapshot-current vmname查),必要时先virsh snapshot-revert到目标快照 - 用
qemu-img commit把当前活跃层合并进其直接父镜像:qemu-img commit -b /path/to/parent.qcow2 /path/to/current.qcow2 - 再用
qemu-img info检查是否只剩单层:qemu-img info /path/to/current.qcow2 | grep "backing file"应无输出 - 最后运行
virsh snapshot-delete --metadata清理残留元数据(如有)
常见误操作与后果
以下做法极易导致空间不释放、快照链断裂或 VM 启动失败:
- 对正在运行的 VM 直接
rm快照 qcow2 文件 —— libvirt 元数据未更新,下次启动报Could not open backing file - 用
virsh snapshot-delete删除中间快照后,立刻virsh start—— VM 可能启动,但磁盘链逻辑未变,空间照占 - 误以为
virsh snapshot-delete --children(不存在此参数)能递归合并 —— 实际上virsh命令不支持该语义,强行加会报错 - 在磁盘空间紧张时删快照却不关机 + commit —— 差量仍驻留内存映射和临时文件,
df看不到释放
真正需要“在线合并”的场景,在 KVM 生态里目前没有安全、标准的 virsh 或 qemu-img 方式;要么接受差量长期存在(只要定期清理叶子快照),要么接受关机窗口做 flatten。最容易被忽略的一点:commit 操作不可逆,执行前务必确认基础镜像有备份。

















