备份复杂存储中的编写者角色

与 VSS 下的所有重要操作一样, 增量 备份和 差异 备份需要请求者和编写者之间的密切合作。

备份类型

基础结构为五种类型的备份提供特殊支持。 这些步骤如下所述:

  • 完整 (VSS_BT_FULL) 。 无论文件的上次备份日期如何,都将备份文件。 将更新每个文件的备份历史记录,此类备份可用作增量备份或差异备份的基础。 如果存在日志文件,这些日志文件可能会因此备份而被截断。

    还原完整备份只需要一个备份映像。

  • 差异 (VSS_BT_DIFFERENTIAL) 。 VSS API 用于确保仅将自上次完整备份以来已更改或添加的文件复制到存储介质;将忽略所有中间备份信息。 这可能包括整个文件或文件中的特定范围。 差异备份与完整备份相关联,在还原完整备份之前,通常无法还原。 如果有日志文件,通常不会由于此备份而截断它们。

    还原差异备份需要原始备份映像和自上次完整备份以来创建的最新差异备份映像。

  • 增量 (VSS_BT_INCREMENTAL) 。 VSS API 用于确保仅将自上次完整备份或增量备份以来已更改或添加的文件复制到存储介质。 这可能包括整个文件或文件中的特定范围。 某些编写器不允许将增量备份与差异备份混合使用。 如果存在日志文件,这些日志文件可能会因此备份而被截断。

    还原增量备份需要原始备份映像和自初始备份以来创建的所有增量备份映像。

  • 日志备份 (VSS_BT_LOG) 。 只有编写器的日志文件 (使用 IVssCreateWriterMetadata::AddDataBaseLogFiles 方法添加到组件的文件,并通过调用 IVssWMComponent::GetDatabaseLogFile) 进行检索。 此备份类型特定于 VSS。 日志备份往往非常频繁。 通常,由于此备份,日志文件将被截断。

  • 复制备份 (VSS_BT_COPY) 。 与VSS_BT_FULL备份类型一样,无论文件的上次备份日期如何,都将备份文件。 但是,不会更新每个文件的备份历史记录,并且此类型的备份不能用作增量备份或差异备份的基础。 日志文件绝不应因复制备份而截断。

部分文件支持

某些编写器通过覆盖其管理的文件部分来支持文件还原。 请求者可以设计为利用这一点,如果是,它通过在 IVssBackupComponents::SetBackupState 中设置信息来指示这一点。

编写器通过在处理 Identify 事件时调用 IVssCreateWriterMetadata::SetBackupSchema 来指示支持的备份类型。 IVssCreateWriterMetadata::SetBackupSchema 方法的 dsSchemaMask 参数是一个位掩码,指示支持哪些类型的备份。 所有编写器都必须支持完整备份。

VSS_BS_DIFFERENTIAL

指示支持差异备份。

VSS_BS_INCREMENTAL

指示支持增量备份。

VSS_BS_LOG

指示支持日志备份。

VSS_BS_COPY

指示支持复制备份。

VSS_BS_EXCLUSIVE_INCREMENTAL_DIFFERENTIAL

指示编写器不支持将增量备份与差异备份混合使用。

编写器可以通过调用 CVssWriter::GetBackupType 来确定正在执行的备份类型。 可以执行此操作的最早点是处理 PrepareForBackup 事件时。 CVssWriter::GetBackupType 将返回 VSS_BACKUP_TYPE 枚举的成员。 如果编写器不支持备份类型,则编写器应将备份视为完整备份。

备份标记

增量备份和差异备份始终与以前的备份相关联。 有两种方法可以绑定备份。 对于简单的数据存储,请求者可以跟踪备份之间的相关性。 但是,对于更复杂的数据存储,编写器需要通过备份维护自己的时间戳;此时间戳可以跟踪日志位置、检查点信息等。 编写器通过在调用 IVssCreateWriterMetadata::SetBackupSchema 时设置VSS_BS_TIMESTAMPED位来指示它需要自己的时间戳。

编写器可以存储每个正在备份的组件的时间戳。 编写器通过调用 IVssComponent::SetBackupStamp 并传入 wszBackupStamp 参数标记的字符串表示形式来存储时间戳。 通常,编写器将在处理 PostSnapshot 事件时调用此方法。 但是,对于不涉及卷影副本的备份,不会发送 PostSnapshot 事件。 在这种情况下,必须在处理 PrepareForBackup 事件时调用 IVssComponent::SetBackupStamp

执行增量备份或差异备份时,请求者将向编写器指示用作此备份基础的上一个备份的备份标记。 编写器可以通过调用 IVssComponent::GetPreviousBackupStamp,在处理 PrepareForBackup 或 PostSnapshot 事件时访问以前的备份标记。 编写器可以使用返回的标记来确定需要备份的内容。

备份策略

文件备份文件策略

通常,仅当执行某些类型的备份时,才需要备份编写器元数据中报告的某些文件。 某些文件可能仅在执行完整备份时是必需的。 仅当执行增量备份或差异备份时,才需要其他文件。 VSS 为编写器提供了一种方法,用于向请求者指示此信息。 使用 IVssCreateWriterMetadata::AddDatabaseFilesIVssCreateWriterMetadata::AddDatabaseLogFilesIVssCreateWriterMetadata::AddFilesToFileGroup 将文件添加到组件时, dwBackupTypeMask 参数指示这些文件必须备份的备份类型。 掩码可以包含以下一个或多个值:

VSS_FSBT_FULL_BACKUP_REQUIRED

完整备份是必需的。

VSS_FSBT_DIFFERENTIAL_BACKUP_REQUIRED

差异备份所必需的。

VSS_FSBT_INCREMENTAL_BACKUP_REQUIRED

增量备份是必需的。

VSS_FSBT_LOG_BACKUP_REQUIRED

日志备份是必需的。

VSS_FSBT_ALL_BACKUP_REQUIRED

对于所有备份类型是必需的;这是默认值。

此规范替代组件的选择性规范。 例如,假设有一个组件,其文件都标有 VSS_FSBT_LOG_BACKUP_REQUIRED 但未 标有VSS_FSBT_FULL_BACKUP_REQUIRED。 假设此组件不可用于备份 (当调用 IVssCreateWriterMetadata::AddComponentbSelectable 为 false) 。 对于日志备份,这意味着必须始终备份此组件中的所有文件。 但是,在完整备份的情况下,不需要备份任何文件,尽管组件的选择性意味着应该备份它。

按上次修改时间备份

编写器指示哪些文件已更改的一种方法是使用差异文件机制。 编写器可以指定仅当组件中的某些文件自特定时间以来已修改时才应备份这些文件。 编写器使用文件规范和上次修改时间调用 IVssComponent::AddDifferencedFilesByLastModifyTimeIVssComponent::AddDifferencedFilesByLastModifyTime 通常在处理 PostSnapshot 事件时调用,尽管可以在处理 PrepareForBackup 事件时调用它。 然后,请求者必须备份与自指定时间以来已更改的文件规范匹配的所有文件。 如果编写器使用备份标记机制,则将根据备份文档中的上一个备份标记确定上次修改时间。 编写器还可以在上次修改时间传入零,这指示请求者负责确定上次备份的时间以及自该时间以来更改的文件的时间。

部分文件备份

编写器指示对请求者的更改的另一种方法是使用部分文件机制。 编写器可以在需要备份的组件文件中指定字节范围;编写器可以在处理 PostSnapshot 或 PrepareForBackup 事件时指定这些文件范围。 编写器调用 IVssComponent::AddPartialFile 将部分文件规范添加到备份。 部分文件规范由路径和文件名以及有关需要备份文件中哪些范围的信息组成。

文件规范规则

IVssComponent::AddDifferencedFilesByLastModifyTimeIVssComponent::AddPartialFile 都可用于修改在标识事件期间提供的文件规范,或将全新的文件添加到规范。 如果编写器使用 IVssComponent::AddDifferencedFilesByLastModifyTime 修改标识事件期间设置的信息,则文件规范必须与当前组件中的某个文件规范完全匹配。 文件规范不得部分重叠当前组件中的文件,并且不能与任何其他组件中的文件匹配。 但是,使用 IVssComponent::AddPartialFile 指定的文件可以部分重叠另一个文件规范。 IVssComponent::AddDifferencedFilesByLastModifyTimeIVssComponent::AddPartialFile 设置的信息会替代前面使用 IVssCreateWriterMetadata 接口设置的信息,以响应 Identify 事件。

常规文件规范可以具有备用位置值 (IVssCreateWriterMetadata::AddFilesToFileGroup) 的 wszAlternateLocation 参数设置,该值指示在备份时从中获取文件的备用位置。 如果通过 differenced-file 或 partial-file 机制设置的文件规范与具有备用位置的现有文件规范匹配,则备份应用程序将从此备用位置获取数据。

如果 IVssComponent::AddDifferencedFilesByLastModifyTimeIVssComponent::AddPartialFile 中设置的文件规范不匹配,并且正在备份的组件中的文件,则所有匹配的文件现在都将添加到备份中。 在执行此操作时,必须注意编写器仅添加已在卷影复制的卷上的文件;否则,请求者可能无法备份这些文件。 如果在处理 PostSnapshot 事件时调用这些函数,则可以使用 CVssWriter::IsPathAffected 方法确定这一点。 如果在处理 PrepareForBackup 事件时调用,编写器必须使用其他方法做出此确定。

没有卷影副本的备份

某些类型的文件可能不需要从卷影复制卷备份。 例如,这通常适用于数据库日志文件。 由于日志文件以单调方式增长,并且编写器可以使用部分文件准确指定要备份的文件部分,因此通常可以备份原始卷中的日志。 作为优化,编写器可以使用 IVssCreateWriterMetadata::AddDatabaseFiles、IVssCreateWriterMetadata::AddDatabaseLogFilesIVssCreateWriterMetadata::AddFilesToFileGroupdwBackupTypeMask 参数中设置的标志来标记需要不同备份类型的卷影副本。 支持的标志包括:

VSS_FSBT_FULL_SNAPSHOT_REQUIRED

完整备份所需的卷影副本。

VSS_FSBT_DIFFERENTIAL_SNAPSHOT_REQUIRED

差异备份所需的卷影副本。

VSS_FSBT_INCREMENTAL_SNAPSHOT_REQUIRED

增量备份所需的卷影副本。

VSS_FSBT_LOG_SNAPSHOT_REQUIRED

日志备份所需的卷影副本。

VSS_FSBT_ALL_SNAPSHOT_REQUIRED

所有备份类型都需要卷影副本;这是默认值。

如果特定卷仅包含不需要此备份卷影副本的组件,则请求者可以跳过为此卷创建卷影副本的步骤。 此卷上的所有数据可以直接从原始卷复制到备份介质。

备份清理

如果编写器需要执行日志截断或其他备份后清理,则执行此操作的适当位置是在处理 BackupComplete 事件时执行。 BackupShutdown 事件将在 BackupComplete 之后发送,因此也可以在 BackupShutdown 事件处理程序中完成一些清理。

备份终止后始终发送 BackupShutdown 事件。 如果请求者在执行备份时异常终止,则会立即发送 BackupShutdown,而无需先发送 BackupComplete。 如果编写器需要清理任何状态,可以在此处完成;但是,日志截断不应在此事件中发生,因为备份不一定完成。

还原策略

还原时编写器的基本任务是验证是否可以在处理 PreRestore 事件时进行还原,以及是否在处理 PostRestore 事件时进行了还原。 更复杂的存储还会在 PostRestore 处理程序中执行恢复过程。 如果还原是增量还原或差异还原的一部分,编写器通常会希望延迟此恢复过程,直到完成所有增量或差异还原。 IVssComponent::GetAdditionalRestores 将指示这是此组件的最终还原,还是要进行更多的还原。 如果 IVssComponent::GetAdditionalRestores 返回 true,则编写器不应对该组件执行其恢复过程。

新目标

如果编写器支持,则请求者可以将数据文件还原到原始备份时间位置以外的位置。 编写器在调用 IVssCreateWriterMetadata::SetBackupSchema 时,通过在 dsSchemaMask 参数中设置VSS_BS_WRITER_SUPPORTS_NEW_TARGET位来指示对此还原模式的支持。 编写器通过调用 IVssComponent::GetNewTargetCount 和 IVssComponent::GetNewTarget 在还原时获取组件文件的新位置。

定向目标

对于复杂的还原方案,编写器可能需要将备份文件的范围映射到相同或不同文件的不同范围。 这可以通过使用定向目标机制来完成。 为此,编写器必须首先通过调用 IVssComponent::SetRestoreTarget 来指示发生这种情况,并传入目标参数的VSS_RT_DIRECTED。 然后,对于每个映射,编写器调用 IVssComponent::AddDirectedTarget。 此方法采用备份中源文件的完整路径,以及将还原到的目标文件的完整路径。 它还会获取其中每个文件的范围列表。 编写器在处理 PreRestore 事件时调用这些函数,然后请求者负责将源文件中的指定范围还原到目标文件中的映射范围。 范围字符串的格式与 IVssComponent::AddPartialFile 中的格式相同

专用编写器元数据

编写器通过备份维护专用元数据以正确执行增量或差异还原通常很有用。 编写器可以在处理 PrepareForBackup 或 PostSnapshot 以存储元数据时调用 IVssComponent::SetBackupMetadata 。 编写器可以通过调用 IVssComponent::GetBackupMetadata 在 PreRestore 或 PostRestore 期间访问此元数据。 还可以使用 IVssComponent::AddPartialFilewszMetadata 参数通过部分文件规范存储元数据;此元数据通过 IVssComponent::GetPartialFilepbstrMetadata参数进行访问。 编写器还可以将元数据传递到 CVssWriter::OnPreRestoreCVssWriter::OnPostRestore 之间。 在 CVssWriter::OnPreRestore 中,元数据是通过调用 IVssComponent::SetRestoreMetadata 设置的。 在 CVssWriter::OnPostRestore 中,通过调用 IVssComponent::GetRestoreMetadata 检索元数据。