更新记录(仅首版,2026年08月01日 发布)
- 首次发布
引用本文(DOI(已登记存档): 10.5281/zenodo.22175809)
以下 DOI 指向先前登记的存档,内容可能与当前正文不同。引用当前正文时,请使用本页网址。
Go Komura(2026)。《卷影复制服务(VSS)的原理与实务——使用中的文件为什么还能备份》。小村软件有限公司。 https://comcomponent.com/zh-CN/blog/vss-volume-shadow-copy-guide/
- DOI(已登记存档)
- 10.5281/zenodo.22175809
- DOI(上次登记版本)
- 10.5281/zenodo.22175810
“想复制其他应用已打开的文件,却被‘进程无法访问该文件’挡了回来”“被要求在不停止核心业务系统的前提下备份数据文件夹”“备份软件为什么能若无其事地复制使用中的数据库文件”——无论是开发业务应用还是运维文件服务器,这都是迟早会碰上的问题。
答案的核心是卷影复制服务(VSS: Volume Shadow Copy Service)。这是二十多年前就内置于 Windows 的机制,Windows Server Backup、系统还原以及市面上几乎所有备份软件,都建立在这个基础之上。1
本文把“使用中也能复制的机制”和“这份副本能守住多少”分开来讨论。 读者对象是被要求实现“使用中文件复制功能”的业务应用开发者,以及负责文件服务器、业务电脑备份运维的信息系统人员。
先给出结论和按目的的阅读顺序,再依次说明 VSS 的登场角色、保存机制、运维时的确认、开发者的判断以及陷阱。技术说明基于截至 2026 年 8 月的一手资料。
在《Windows I/O 的深层》系列中,我们已经看过缓存管理器与 NTFS 的内部结构。本文作为它的续篇,讨论紧贴在卷之上插入的“快照”这一层。
1. 先说结论
VSS 是与编写器协同、把应用的写入短暂静止下来,再从那一时刻的副本中取得备份的机制。仅仅创建了卷影副本,并不等于可以不再向其他介质备份。
它是做什么的机制
VSS 是一组 COM 接口和一个协调服务,用来让“应用仍在持续写入的卷”也能备份。它从 Windows XP 起就已内置。2
登场角色是 3 个职责加一个协调者。请求卷影副本的请求程序(备份软件)、在应用一侧保证数据一致性的编写器(SQL Server 等)、实际创建快照的提供程序,由 VSS 服务居中协调。1
静止点由“冻结编写器(最长 60 秒)→创建快照(10 秒以内)→解冻”产生。超过限制时间,创建就会中止,由请求程序重来一次。1
把保存方式和一致性保证分开看
Windows 标准的系统提供程序采用写时复制方式。它不复制整个卷,只把快照之后将被改写的数据块,在改写前转存到差异区域(diff area)。差异区域必须位于 NTFS 卷上。1
有没有编写器的配合,副本的质量完全不同。没有配合时创建的快照,等同于“断电瞬间的磁盘”(崩溃一致);有配合时,日志滚动和缓存刷新已经完成,得到的是应用自身保证可恢复的一致状态(应用程序一致)。31
运维和开发要确认的东西不同
运维侧的确认工具是 vssadmin。用 list shadows / list writers / list shadowstorage 查看现状,用 resize shadowstorage 调整差异区域的上限。差异区域一旦耗尽,就会从最旧的卷影副本开始被悄悄删除。451
在自制应用里嵌入 VSS 请求程序是一项大工程。它是基于 COM 的原生 API,官方没有面向 .NET 的封装。多数情况下,重试、调整共享模式、短时间停止就够了;真正需要 VSS 时,把 DiskShadow 写成脚本才是现实的解法(仅限 Windows Server)。67
卷影副本本身并不是备份。写时复制的差异数据依赖原卷上完好无损的数据块,因此对磁盘故障、失窃这类连原卷一起丢失的故障无能为力。面对勒索软件同样靠不住,卷影副本会被直接删除(7.3),也会因大量改写导致差异区域耗尽(7.4)。只有与保存到其他介质的备份组合起来,它才有意义。1
按目的和症状选择读法
| 想了解的事、遇到的问题 | 先读这里 |
|---|---|
| 想知道使用中的文件为什么不能直接复制 | 第 2 章:共享冲突、一致性、运维这三道墙 |
| 想知道 VSS 的角色分工,以及为什么能在很短时间内做出副本 | 第 3 章:登场角色、4.1:写时复制、4.2:静止点的流程 |
| 想知道“用了 VSS”和“一致的备份”之间的区别 | 4.3:编写器是否配合决定一致性 |
| 备份因 VSS 错误而失败 | 第 5 章:确认命令、7.2:编写器错误的排查 |
| “以前的版本”消失了,想重新审视保留期限 | 5.1:以前的版本、7.4:差异区域与消失的监控 |
| 拿不准要不要把 VSS 嵌入自制应用 | 先看 6.2:按需求判断的表,再看 6.1:请求程序 和 6.3:编写器 |
| 想知道只靠卷影副本能否应对故障和攻击 | 第 7 章:与备份的区别和运维陷阱 |
想理解原理的读者可以从第 2 章顺序读下来,运维人员可以读第 5 章和第 7 章,开发者可以从 6.2 的判断表开始。
图中实线表示始终成立的关系,虚线表示带条件的关系(成立条件写在详情页各关系的说明中)。关系的完整列表(共 26 条,附依据与确信度)以及主要概念的定义,汇总在知识地图详情页(日文)。数据:JSON-LD / Turtle
2. 问题设定——使用中的文件为什么不能直接复制
先确认“打不开”的原因
起点是 Windows 的文件共享模式。在 Windows 上打开文件时(CreateFile),要以共享模式(dwShareMode)声明“在我打开期间,允许其他进程做什么”。只要有进程以不允许读取共享的方式打开着文件,之后想以读取方式打开的进程就会因共享冲突(ERROR_SHARING_VIOLATION,错误 32)而失败。8 在 .NET 中,它表现为大家熟悉的 IOException(“文件正由另一进程使用,因此该进程无法访问此文件”)。
重要的是,这不是 bug,而是为保护数据而存在的正确机制。如果正在写入的文件被中途读取,读取方拿到的就是“写了一半的半成品状态”。正如《文件对接中互斥控制的基础知识》中详细讨论过的,互斥控制的设计是应用间对接的基础。
但这个正确的机制与备份存在根本冲突。这里有三道各自独立的墙。
第一道墙:共享冲突导致打不开复制源
数据库或业务应用一直开着的文件,可能根本就打不开,无法作为复制源。
第二道墙:即使打开了,副本内容也不一致
即便能打开(对方允许读取共享),复制也需要时间。复制期间应用仍在写入,于是文件的前半段和后半段会来自不同时刻,多个文件之间(数据本体与日志等)也会对不上。
而且正如《缓存管理器》那一篇中看到的,写入首先落在内存中的缓存上,所以只看磁盘上的文件未必是最新内容。“能读”和“能以一致的状态复制”是两个不同的问题。
第三道墙:不能为了复制而长时间停机
“那就停掉应用再复制”这话本身没错,但对全天候运行的业务系统和文件服务器来说无法接受。
也就是说,需求是“不停应用,也要拿到某一瞬间一致状态的副本”。让每个应用各自解决太过沉重,于是就有了操作系统层面的机制 VSS。VSS 以 COM 接口构成的框架形式提供,让应用持续向卷写入的同时也能对卷执行备份。2
3. VSS 的登场角色——请求程序、编写器、提供程序
VSS 的构成可以归纳为三种角色,以及居中协调它们的服务。1
| 角色 | 承担的职责 | 具体例子 |
|---|---|---|
| VSS 服务 | 协调各个角色之间的配合。属于 Windows 的一部分 | VSS 本体 |
| 请求程序 | 请求创建卷影副本(以及导入、删除)的软件 | 各类备份软件。Windows Server Backup 和 DiskShadow 也是请求程序 |
| 编写器 | 在应用一侧保证备份对象数据一致性的部件 | 由 SQL Server、Exchange Server 提供。注册表等 Windows 组成部分的编写器随操作系统附带 |
| 提供程序 | 实际创建并维护卷影副本的部件 | Windows 标准的系统提供程序(写时复制)。也有存储设备一侧的硬件提供程序 |
备份软件与应用分担角色
这种分工的妙处在于,互不了解的产品之间也能协同。备份软件(请求程序)并不了解 SQL Server 的内部结构,但按下面的分工,仍然能取得一致的备份。19
- SQL Server 的编写器以元数据的形式申报“应该备份的文件集合(组件)”。
- 编写器在创建静止点的前后整理好自己的数据。
- 请求程序按照这份申报与协同流程执行备份。
在 Windows 上运行的第三方备份软件,几乎全都是 VSS 请求程序。1
出问题时,也用这三种角色决定该查哪里
信息系统运维中真正需要意识到这三种角色的场景,是故障排查。备份软件失败究竟是请求程序(软件一侧)的问题、某个编写器(应用一侧)的问题,还是提供程序与差异区域(底层一侧)的问题,要查的地方完全不同(第 5 章、第 7 章)。
4. 快照的原理——写时复制与“静止点”
4.1. 写时复制——不复制整个卷也能保存“那一瞬间”
只转存改写前的数据块
听到“快照”容易联想到整个卷的复制,但 Windows 标准的系统提供程序使用的是写时复制(copy-on-write)方式。在创建快照的那一刻,它几乎什么都不复制。
此后,当原卷上的数据块被改写时,会先把改写前的数据块转存到差异区域(diff area,卷影副本存储区),再放行这次写入。1 需要转存的只有每个数据块的第一次改写,对已转存的数据块再次覆盖并不会增加差异区域的占用。
| 时点 | 原卷 | 差异区域 |
|---|---|---|
| T0:创建快照 | 1 2 3 4 5 | (空) |
| T1:改写数据块 3 | 1 2 3’ 4 5 | 3(转存改写前的内容) |
| T2:读取卷影副本 | 数据块 1 2 4 5 从这里读 | 数据块 3 从这里读 |
读取时把原卷与差异区域合成起来
想读“那一瞬间的卷”时,未变化的数据块从原卷读,已变化的数据块从差异区域读,再合成起来。因为只复制发生变化的部分,创建是一瞬间的事,占用的容量也只有差异部分。
反过来说,写入越多的卷,差异区域消耗得越快。占用量由什么决定,将在 7.4 中详细说明。差异区域位于与原数据同一台机器的 NTFS 卷上。1
支撑这套机制的,是系统提供程序的组成文件 swprv.dll,以及插入卷 I/O 的驱动程序 volsnap.sys。1 如果对“如何插入 I/O 栈”感兴趣,可以再读《筛选器驱动程序与迷你筛选器》。
另外,方式还有拆分镜像的完整复制,以及把变更写到另一个卷的写时重定向,硬件提供程序会在存储设备一侧选用最合适的方式。1
4.2. 创建静止点的流程——冻结 60 秒、创建 10 秒的协同
如果说写时复制解决的是“怎么保存”,那么 VSS 的看家本领就是“保存哪一时刻的状态”,也就是静止点的做法。卷影副本的创建按以下流程推进。1
flowchart TB
R["请求程序请求创建<br/>枚举编写器并收集元数据"] --> M["各编写器用 XML 申报<br/>备份对象(组件)"]
M --> P["各编写器准备数据<br/>滚动日志、刷新缓存等<br/>整理为可恢复的一致状态"]
P --> F["冻结编写器的写入 I/O<br/>(读取仍可进行。最长 60 秒)"]
F --> FS["VSS 刷新文件系统缓冲区<br/>并冻结文件系统"]
FS --> C["提供程序创建卷影副本<br/>(10 秒以内。其间写入 I/O 保持冻结)"]
C --> T["释放文件系统 → 解冻编写器(thaw)<br/>应用恢复写入"]
T --> B["请求程序以卷影副本为源<br/>用较长时间执行备份"]
图1:卷影副本创建的流程。停顿只有几秒到几十秒,备份本体是针对快照执行的
停顿时间与备份耗时是两回事
要点有 3 个。
- 应用停下来的只是创建静止点的一瞬间。规定冻结在 60 秒以内、提供程序的创建(提交)在 10 秒以内,超时就中止创建,由请求程序重来。1 动辄数小时的备份本体,是针对已经做好的只读卷影副本执行的,应用照常运行。
- 冻结期间仍可读取。停下来的只有写入 I/O。1
- 文件系统也会被冻结。VSS 先刷新文件系统缓冲区再冻结,因此留在缓存中的写入和文件系统元数据,会以一致的顺序进入快照。1
4.3. 崩溃一致与应用程序一致
这里出现了一个决定备份质量的重要区分。
没有编写器:与从突然停机中恢复相同的状态
没有编写器配合创建的卷影副本,用 Microsoft 的术语说就是崩溃一致(crash consistent)状态。官方定义是“与系统在灾难性故障导致突然关机之后所处状态等价的磁盘状态”,从这种状态还原“等价于突然关机后的重新启动”。3 作为文件系统它并没有损坏,但在应用看来就是“写入过程中被拔掉电源的那一瞬间”。具备事务日志恢复机制的数据库大多能恢复,但前提是要执行恢复处理。
有编写器:由应用准备好可恢复的一致状态
有编写器配合时,在静止点之前各编写器会滚动事务日志、刷新缓存,把数据整理成应用自身保证“从这里能够正确恢复”的一致状态。1 这就是应用程序一致,也是编写器这一机制存在的理由。
需要注意的是,编写器保证的是“作为应用一致且可恢复的状态”,并不会擅自提交并完成正在执行的事务。未提交的工作会在还原时回滚(与数据库通常的恢复行为相同)。编写器实现这一质量保证时不必停止应用,只需要几十秒的冻结。
备份软件的设置里之所以有“使用 VSS”“保证应用程序一致性”这类选项,正是这一区分的体现。如果只是文件服务器上的普通文件,崩溃一致基本不成问题;但对于承载数据库或邮件存储的服务器,相应编写器是否正常,直接就是备份的质量本身。
5. 运维命令的实务——vssadmin 与“以前的版本”
信息系统运维中确认 VSS 状态的工具是 vssadmin,要在管理员权限的命令提示符下执行。先用列表确认状态,差异区域的上限变更则要在确认必要性和消失风险之后再做。
确认对象与命令的适用范围
现行的命令参考中整理出 list shadows / list writers / delete shadows / resize shadowstorage 在客户端和服务器上都可使用。4 Windows Server 系列的参考中,除此之外还列出了 create shadow / list shadowstorage / list providers 等。5 另外,vssadmin 能管理的只有系统提供程序创建的卷影副本。1
区分状态确认命令与上限变更命令
| 命令 | 能看到什么 | 实务中的用处 |
|---|---|---|
vssadmin list shadows |
现存卷影副本的列表(创建时间、目标卷、卷影副本卷名) | 确认“可用于还原的静止点最早能回到什么时候”。确认备份之后是否残留了垃圾 |
vssadmin list writers |
已注册编写器的列表及其状态 | 备份软件因 VSS 错误失败时的初步定位。看是哪个编写器(即哪个应用)失败了 |
vssadmin list shadowstorage |
卷影副本存储区(差异区域)的使用量、分配量与上限 | 调查“以前的版本消失了”。看是否一直顶着上限 |
vssadmin resize shadowstorage |
─(变更差异区域的上限) | 想保留的版本数所需的差异区域不够时用于扩容10 |
如果 list writers 的结果显示编写器处于错误状态,该怀疑的不是 VSS 本体,而是提供该编写器的应用一侧。确认相关应用的服务状态,以及应用程序/系统事件日志(第 7 章)。
上限变更要与确认命令区别对待
resize shadowstorage 的 /maxsize 可以带 KB/MB/GB 等单位指定上限,不指定则为无限制。要注意的是,文档明确写着变更存储区上限(尤其是缩小)本身就可能导致卷影副本消失。10 对于希望保留多个版本的卷,不要随意缩小它的上限。
5.1. 与“以前的版本”的关系
在文件服务器上启用“共享文件夹的卷影副本(Shadow Copies of Shared Folders)”后,系统会定期保留共享上文件某一时点的副本,用户可以不借助管理员之手,从“以前的版本”还原被删除或被覆盖的文件。1 这是能切实减少服务台工时的、VSS 最贴近日常的应用。
不过它有上限。系统提供程序的卷影副本每个卷最多 512 个,其中共享文件夹的卷影副本功能默认维持的最多为 64 个(可通过注册表的 MaxShadowCopies 更改)。1
而且正如下一章之后所述,差异区域不足时会从最旧的版本开始自动删除。“能留下多少个版本”不由设定的版本数决定,而由写入量和差异区域的大小决定,这样理解更稳妥。
6. 开发者该如何介入——自制应用需要 VSS 吗
以下是开发者的视角。当被要求“加一个连使用中文件也能复制的备份功能”时,应该如何与 VSS 打交道?
请先用 6.2 的判断表看清是否真的需要 VSS,然后再选实现方式。 6.1 讲的是请求创建副本的“请求程序”,6.3 讲的是让别人能取走自制应用数据的“编写器”。
6.1. 自己实现请求程序是一项大工程
VSS 的 API 无论请求程序还是编写器,都以 COM 和 C++ 接口的形式提供(请求程序的核心是 IVssBackupComponents)。6 官方没有提供面向 .NET 的封装,而且从编写器的元数据收集、快照集的管理到出错时的善后都必须正确实现,所以它不是能随手塞进业务应用的一个功能。我们在承接开发的报价中,也把“自己实现 VSS 请求程序”当作独立的开发项目来处理。
先考虑现成软件,Windows Server 上则考虑 DiskShadow
现实的解法有两个。第一,交给现成的支持 VSS 的备份软件。第二,如果是 Windows Server,通过脚本使用 DiskShadow。
DiskShadow 是随操作系统附带的 VSS 请求程序,除交互模式外还有脚本模式(diskshadow /s script.txt),可以用一个脚本写完卷影副本的创建、公开为驱动器号(expose)、执行负责复制处理的批处理(exec)以及收尾清理。71 “创建卷影副本 → 用自己写的复制处理从中取出文件 → 删除”这一整套流程,不用写一行 COM 就能搭起来。
不过DiskShadow 仅限 Windows Server,客户端操作系统中并不包含。1 如果需求还要覆盖客户端电脑,到这一步就会更倾向于采用现成的备份软件。
6.2. 到底需不需要 VSS——判断表
以我们的经验,关于“复制使用中文件”的咨询,大部分不用 VSS 也能解决。请先看清需求的层级,再选工具。
| 需求 | 现实的解法 | 是否需要 VSS |
|---|---|---|
| 其他应用正在写入的文件,稍等一会儿能读到就行 | 重试(重试加等待时间)。共享冲突多数是暂时状态 | 不需要 |
| 对方应用允许读取共享 | 按相同的共享模式打开(.NET 中指定 FileShare.ReadWrite)。但读到半成品的风险要自己管理 |
不需要 |
| 可以在业务空档(夜间、休息时段)停止应用 | 停止期间复制。最简单也最可靠 | 不需要 |
| 能与对方应用约定对接方式 | 改成完成后用重命名交接这类原子性的对接设计(参见互斥控制那篇文章) | 不需要 |
| 想把无法停止的应用的整套数据以一致状态复制出来 | VSS。先用现成备份软件,其次是 DiskShadow 脚本(仅限 Server),最后才是自己实现请求程序 | 需要 |
6.3. 自制应用该不该注册编写器
也梳理一下反方向的问题:“自制的业务应用该不该提供 VSS 编写器?”写了编写器,无论客户用哪款备份软件,都能以应用程序一致的方式取走本应用的数据。
快速编写器不会让写入静止
还有一种比普通编写器更简易的机制,叫快速编写器(IVssExpressWriter),但它只是注册“哪些文件纳入、哪些排除”这类元数据声明而已。6
它不会收到冻结、解冻之类的通知,因此无法配合快照创建让应用的写入静止下来。只有当保存设计本身在写入中途被取走也不会损坏(崩溃一致即可满足)时,才可以使用快速编写器;如果需要在静止点上协同,就必须实现普通的编写器。
是否需要自制编写器,从保存方式来判断
判断的标准很简单。
- 如果数据放在 SQL Server 等数据库中,就不需要。数据库一侧的编写器会保证一致性。1
- 如果只是普通的文件保存,先从保存处理一侧的设计来解决。只要做成先写完临时文件再用重命名替换的原子性保存,即使是崩溃一致的快照,也不会留下“损坏的保存文件”。
- 值得考虑注册编写器的,只限于拥有跨多个文件的自有数据存储、且需要在静止点上保持相互一致的应用。也许更该先重新审视的是:这种规模的数据是否有必要用自有格式来承载。
7. 陷阱——运维中真正会起作用的四个
不只要确认“静止点有没有做出来”,还要确认“会不会丢失”“质量是否够用来还原”。 以下 4 点在运维时需要分开考虑。
7.1. VSS 本身并不是备份
这是最重要的陷阱。系统提供程序的卷影副本,是位于与原数据同一台机器磁盘上的差异数据。它并不另外保存一份完整副本,而是把原卷上未被改写的数据块与差异区域合成后读取。
因此,面对磁盘故障、机器失窃丢失这类连原卷一起失去的情况,它无能为力。 即使只把差异区域放到另一个卷上,这种依赖关系也不会改变。差异区域丢失时同样无法再合成。
对于加密整个卷的勒索软件,也不能指望卷影副本。加密写入本身确实会把改写前的内容转存起来,但在实际攻击中,卷影副本会因被删除,或因大量改写导致差异区域耗尽而丢失。这一点在 7.3 和 7.4 中讨论。
Microsoft 的文档也明确区分了卷影副本与备份:“从卷影副本复制到磁带等介质上的内容才是备份,复制完成后卷影副本可以删除。”1 卷影副本是静止点,是从误操作中快速还原的手段,而不是其他介质、其他场所备份的替代品。
7.2. 编写器的错误是应用一侧的问题
备份软件因“VSS 错误”失败时,按以下顺序确认。
- 用
vssadmin list writers确定是哪个编写器失败了。 - 确认提供该编写器的应用或 Windows 组成部分的服务状态。
- 查看应用程序/系统事件日志,调查相关应用一侧的原因。
编写器的实体是应用程序(或 Windows 组成部分)一侧的部件。1 被“备份软件的错误”这一表象牵着走,一直只查备份软件,只会绕远路。排查的一般做法,就是《维护没有源码也没有文档的系统》中也讲过的“从可观测的事实缩小嫌疑范围”这一套路。
7.3. 勒索软件会专门来删除卷影副本
这是防御方必须知道的事实。既然“以前的版本”能还原,那被勒索软件加密后是不是也能还原——人们容易这样期待,但众所周知,很多勒索软件会在加密前后删除卷影副本,专门来堵死这条还原路径。删除卷影副本只要有管理员权限就能用正规命令完成,所以它挡不住已经入侵的攻击者,成不了最后一道防线。因此,对策的支点有以下三个。
- 把卷影副本定位成“有了会更快”,而不是“恢复计划的一部分”。
- 另外持有攻击者无法触及的离线备份、异地备份。
- 不给日常运维使用的账户管理员权限。
涵盖备份、加密到报废的电脑生命周期防护,可以一并阅读《BitLocker 实务指南》《电脑报废检查清单》。
7.4. 差异区域耗尽后,会从最旧的版本开始悄悄消失
决定占用量的不是写入次数,而是范围
正如第 4 章所见,写时复制消耗差异区域的时机,是快照创建之后每个数据块第一次被改写时。对已转存的数据块再覆盖多少次,占用都不会增加,因此占用量不由“写入的次数”决定,而由“自保留中的快照以来被改写的数据块范围有多大”决定。
消失的版本可以在 System 日志中确认
差异区域达到上限后,该卷的卷影副本会从最旧的开始依次被删除。1 由于不会向交互用户发出任何通知,往往要到“本以为能回到上周那一版”却回不去时才被发现。不过它并非完全无声,System 日志中会记录来源为 volsnap 的事件(例如无法确保差异区域而删除时的 25,扩展失败或达到上限而中止时的 35/36 等)。除定期确认外,把这些 volsnap 事件纳入监控和告警对象,就能第一时间察觉丢失。
把需要的保留期限与差异区域的使用量对照起来看
大量文件更新、批量转换、磁盘碎片整理这类“把卷大面积扫一遍”的处理之所以会一下子吃光差异区域,正是因为占用量“由改写的范围决定”这一性质。
请定期用 vssadmin list shadowstorage 确认使用量,检查保留的版本数是否满足业务要求(“发现误删除最长要几天”),必要时扩大上限。510
8. 总结
理解 VSS 时,分成“整理什么”“怎么保存”“怎么运维”三部分就容易理清。
整理什么:即使在使用中也要做出一致的静止点
使用中的文件不能直接复制,源于共享冲突和一致性的问题,而这是保护数据的正确机制。对“不停机也要一致的副本”这一需求,操作系统层面的答案就是 VSS。
VSS 是由 VSS 服务居中协调请求程序(请求)、编写器(保证一致性)、提供程序(创建)三种角色的框架,让互不了解的备份软件与业务应用能够协同。
怎么保存:短时间做出静止点,另行备份
系统提供程序采用写时复制方式,静止点由“冻结编写器(最长 60 秒)→创建(10 秒以内)→解冻”产生。没有编写器配合是崩溃一致,有配合是应用程序一致。
卷影副本不是备份。它只是依赖原卷上完好数据块的差异数据,面对磁盘故障这类原卷丢失无能为力,面对勒索软件也会因卷影副本被删除或差异区域耗尽而靠不住。请与离线备份、异地备份组合使用。
怎么运维:确认状态,只在必要的范围内介入
运维确认用 vssadmin(list shadows / list writers / list shadowstorage)。编写器的错误要怀疑应用一侧,差异区域的使用量要定期查看。
开发者应先用判断表确认能否靠重试、共享模式、停机时间、对接设计解决,真正必要时才走向 VSS。比起自行实现,DiskShadow 脚本(仅限 Server)或现成软件才是现实的解法。
相关文章
- 文件对接中互斥控制的基础知识 - 文件锁与原子 claim 的最佳实践
- Windows I/O 的深层(第 4 回)——缓存管理器:你的 WriteFile 何时才能到达磁盘
- Windows I/O 的深层(第 5 回)——NTFS 的内部结构:从 MFT 理解文件系统
- 接手了没有源代码也没有文档的系统——在不停机的前提下运维与维护的实务步骤
- BitLocker 实务指南——从恢复密钥的管理入手的驱动器加密
- 报废 Windows 电脑前应该做的事——数据清除、账户解绑、备份的实务检查清单
相关咨询领域
合同会社小村软件承接包含“使用中文件复制、备份功能”在内的业务应用设计与开发,文件对接相关的共享冲突与备份失败(VSS 编写器错误)的原因调查,以及文件服务器备份与版本管理的运维梳理。也可以从“这个需求到底需不需要 VSS”的判断开始。
参考链接
-
Microsoft Learn, Volume Shadow Copy Service (Windows Server)。关于 VSS 服务、请求程序(备份软件。Windows Server Backup 和 DPM 属于此类,Windows 上几乎所有备份软件都是请求程序)、编写器(由 SQL Server、Exchange Server 等提供,注册表等 Windows 组成部分的编写器随操作系统附带)、提供程序的角色分工;卷影副本创建的步骤(收集编写器元数据 → 通过完成事务、滚动日志、刷新缓存进行准备 → 冻结写入 I/O,限时 60 秒以内且读取仍可进行 → 刷新并冻结文件系统缓冲区 → 提供程序在 10 秒以内完成创建 → 解冻,超时则中止并由请求程序重试);完整复制、写时复制、写时重定向这 3 种方式;系统提供程序采用写时复制方式,差异区域(diff area)必须位于 NTFS 卷上;组成文件为 swprv.dll 与 volsnap.sys;差异区域空间耗尽时该卷的卷影副本会从最旧的开始被删除;软件卷影副本每个卷最多 512 个,共享文件夹的卷影副本默认维持 64 个(可通过 MaxShadowCopies 更改);共享文件夹的卷影副本让用户无需管理员协助即可还原被删除、被修改的文件;卷影副本与备份的区别(复制到介质上的内容才是备份,卷影副本可以删除);DiskShadow 是仅限 Windows Server 的 VSS 请求程序;vssadmin 只能管理系统提供程序创建的卷影副本等内容。 ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12 ↩13 ↩14 ↩15 ↩16 ↩17 ↩18 ↩19 ↩20 ↩21 ↩22 ↩23 ↩24 ↩25 ↩26 ↩27 ↩28
-
Microsoft Learn, Volume Shadow Copy Service (Win32)。关于 VSS 是一组 COM 接口,实现了让系统上的应用程序持续向卷写入的同时也能对卷执行备份的框架,以及它自 Windows XP 起获得支持等内容。 ↩ ↩2
-
Microsoft Learn, VSS Glossary: crash consistent state。关于崩溃一致状态是“与系统在灾难性故障导致突然关机之后所处状态等价的磁盘状态”;从这类卷影副本集还原“等价于突然关机后的重新启动”;这是在没有编写器支持的情况下被做成卷影副本的数据的默认状态等内容。 ↩ ↩2
-
Microsoft Learn, vssadmin。关于 vssadmin 是显示当前卷影副本以及已安装的全部卷影副本编写器、提供程序的命令,以及 delete shadows / list shadows / list writers / resize shadowstorage 各子命令被整理为客户端与服务器均可使用等内容。 ↩ ↩2
-
Microsoft Learn, Vssadmin (Windows Server 2012 R2 and 2012)。关于 Windows Server 系列参考文档中作为 vssadmin 子命令列表记载了 add shadowstorage / create shadow / delete shadows / delete shadowstorage / list providers / list shadows / list shadowstorage(列出系统上全部卷影副本存储区的关联)/ list volumes / list writers / resize shadowstorage 等内容。 ↩ ↩2 ↩3
-
Microsoft Learn, Volume Shadow Copy API Interfaces。关于 VSS API 以支持创建请求程序与编写器的 COM 及 C++ 接口形式提供;定义了面向请求程序的 IVssBackupComponents 系列接口、面向编写器的 IVssCreateWriterMetadata 系列接口,以及面向简易的快速编写器的 IVssExpressWriter 等内容。 ↩ ↩2 ↩3
-
Microsoft Learn, Diskshadow。关于 DiskShadow 是公开 VSS 功能的工具,具备交互式命令解释器与脚本模式(diskshadow /s script.txt);执行时需要本地 Administrators 组的成员身份;通过 add、create、expose(把持久卷影副本公开为驱动器号等)、exec(执行本地的文件)、delete shadows 等命令,可以把从创建卷影副本到公开、执行备份脚本的整个流程写进一份脚本等内容。 ↩ ↩2
-
Microsoft Learn, CreateFileW function。关于打开文件时用 dwShareMode 指定允许后续打开操作的共享访问(读取、写入、删除);请求的访问与既有句柄的共享模式冲突时,打开操作会因共享冲突(ERROR_SHARING_VIOLATION)而失败等内容。 ↩
-
Microsoft Learn, Overview of Processing a Backup Under VSS。关于备份处理中请求程序与编写器如何协同;编写器用只读的元数据(Writer Metadata Document)申报自己负责的文件集合(组件),请求程序据此解读并选择备份对象,记录到自身的元数据(Backup Components Document)中;编写器在卷影副本创建前暂停 I/O,完成后回到正常运行等内容。 ↩
-
Microsoft Learn, Vssadmin resize shadowstorage。关于该命令用于变更可用作卷影副本存储区的最大容量;不指定 /maxsize 时存储区的使用量不受限制;数值可以用 KB/MB/GB/TB/PB/EB 为单位指定;文档警告变更存储区关联的容量有可能导致卷影副本消失等内容。 ↩ ↩2 ↩3
相关文章
共享相同标签的最新文章。可以围绕相近的主题进一步加深理解。
OneDrive“按需文件”与业务应用——占位符打破的前提与对策
桌面上的 CSV 读不了,导入处理以“找不到文件”中断——原因可能是 OneDrive 的 KFM 与按需文件。本文讲解占位符的机制与属性判断,以及应用端和信息系统部门各自的对策。
睡眠恢复后就出故障的应用——电源事件机制与扛得住恢复的业务应用设计
打开笔记本电脑时业务应用的通信已经断开——原因是设计没有考虑睡眠。本文依据一手资料讲解 WM_POWERBROADCAST 的通知流程、Modern Standby 的行为、断开与重连的设计、睡眠抑制以及调查命令。
多线程实战最佳实践 C 语言篇——以 Win32 API 的方式安全编写
C 语言 × Win32 的多线程自有定式:用 _beginthreadex 创建线程、SRW 锁与条件变量、Interlocked,以及停止事件 + WaitForMultipleObjects 的停止设计。本文还梳理 TerminateThread 的危险与 DllMa...
多线程实战最佳实践 C++ 篇——用 RAII 和 jthread 从结构上杜绝问题
C++ 的多线程里数据竞争就是未定义行为。本文梳理 std::thread 析构函数的陷阱、jthread 与 stop_token 的停止设计、scoped_lock 的死锁规避、atomic 的正确定位,直到与 Win32 同步 API 的区分使用。
多线程实战最佳实践 .NET 篇——增加线程之前必须先定好的事
面向 .NET/C# 梳理防止“线程一开就偶尔崩溃、偶尔卡死”的设计做法,涵盖不自己创建线程而依托 Task、减少共享可变状态、加锁的纪律、用 CancellationToken 设计停止流程,直到 UI 线程的处理方式。
相关主题
与本文相近的主题页面。以本文为起点,可以进一步了解相关服务和其他文章。
Windows 技术主题
汇整 KomuraSoft LLC 关于 Windows 开发、故障调查与既有资产活用文章的主题中心。
常见问题
汇总了咨询这一主题时常见的问题。
- 有了卷影副本,是不是就不需要备份了?
- 并不会变得不需要。Windows 标准系统提供程序创建的卷影副本是写时复制方式的差异数据,并不会另外保存“那一时刻的完整副本”,而是依赖原卷上尚未被改写的数据块。即使把差异区域(diff area)配置到另一个卷上,只要原卷丢失就依然无法还原,对磁盘故障、电脑失窃丢失这类连原卷一起失去的情况完全无能为力。对勒索软件也一样,加密写入本身确实会把改写前的数据块转存到差异区域,但在实际攻击中,卷影副本会因被删除,或因大量改写导致差异区域耗尽而丢失,所以不能指望它。Microsoft 的文档同样区分了两者:从卷影副本把数据复制到磁带等介质上得到的才是备份,复制完成后卷影副本本身可以删除。卷影副本是“制作备份用的静止点”和“从轻微误操作中快速还原的手段”,不能替代保存到其他介质、其他场所的备份。
- 我想在自制的业务应用里复制使用中的文件,应该用 VSS 吗?
- 现实的做法是先找一条不用 VSS 也能解决的路。VSS 的请求程序必须用基于 COM 的原生 API(IVssBackupComponents 等)编写,官方没有提供面向 .NET 的封装,因此把它嵌入自制应用是一项相当大的工程。如果需求只是“其他进程正在写入的文件,迟早能读到就行”,重试就够了;如果“对方允许读取共享”,按相同的共享模式打开即可。如果应用可以短时间停止,在业务的空档期复制最为可靠。只有“把无法停止的应用的整套数据以一致的状态复制出来”这种需求才轮到 VSS 出场,而且即使到了这一步,也应先考虑支持 VSS 的备份软件或把 DiskShadow 写成脚本,而不是自行实现。
- vssadmin list writers 显示编写器处于错误状态,该怎么办?
- 基本原则是把它当作提供该编写器的应用程序一侧的问题来调查。vssadmin list writers 会带状态列出已注册的编写器,先据此确定是哪个编写器失败了。编写器由 SQL Server 之类的应用程序或 Windows 组成部分(注册表等)提供,所以出错的原因大多不在 VSS 本体,而在于相关应用的服务状态,或记录在应用程序/系统事件日志中的错误。可以重启相应服务、排查复现条件,如果仍未解决,就去查该应用的支持信息。备份软件因 VSS 错误而失败时,初步定位也是同样的步骤。
- 卷影副本在不知不觉中消失了,这是为什么?
- 最典型的原因是差异区域(卷影副本存储区)容量不足。在写时复制方式下,快照创建之后每个数据块第一次被改写时,改写前的内容都会被转存到差异区域,因此被改写的范围越大,消耗的差异区域越多。达到分配的上限后,Windows 会从最旧的卷影副本开始依次删除以腾出空间。这个过程不会通知交互用户,是悄无声息发生的,所以往往要等到“本以为能用以前的版本回到上周那一版,结果却发现没有了”时才被察觉(System 日志中会记录来源为 volsnap 的事件 25 等,把它纳入监控就能及时发现)。可以用 vssadmin list shadowstorage 确认使用量与上限,必要时用 vssadmin resize shadowstorage 扩大上限。不过也要注意,上限的变更(尤其是缩小)本身就可能导致卷影副本消失。
- 文件资源管理器里的“以前的版本”和 VSS 是什么关系?
- “以前的版本”是从 VSS 创建的卷影副本中取出文件旧版本的入口之一。在文件服务器上启用“共享文件夹的卷影副本”(Shadow Copies of Shared Folders)后,系统会定期创建卷影副本,用户右键点击共享文件夹上的文件,就能自己从以前的版本还原。不用麻烦管理员就能修正误删除、误覆盖,这是它的优点。不过它的实体就是卷影副本,可保留的版本数存在上限,差异区域不足时也会从最旧的版本开始消失。正如正文所述,“有以前的版本就不需要备份”这个说法并不成立。