为什么差异备份不能指定其基础?

elm*_*007 19 sql-server backup

这是我的第一篇 DBA.SE 帖子,所以请告诉我任何错误,谢谢!

我是一名新的 DBA(不是 IT 专业人员,只是公司中没有其他人可以这样做),所以解释越基本越好。我一直在阅读有关数据库备份策略(或者,我已经学会将其称为“恢复策略”)的文章。我了解完整、差异和事务日志备份的作用,但我想知道为什么差异备份只能基于最近的完整备份。

如果差异备份是自上次完整备份以来发生变化的所有内容,那么为什么差异不能基于我选择的任何备份?更清楚地说,我问的是在进行备份时指定基础,而不是在恢复时。我假设在恢复时您会选择正确的基数和相应的差异来执行恢复(不使用由基数 B 制成的差异从基数 A 恢复)。

阻止此功能实现的原因是什么?我想一定是有原因的,我只是不知道它是什么。

注意:我知道不能指定基数,但我的问题是为什么不指定?(我也对“你为什么要?”的讨论不感兴趣)

比喻

这是我如何理解差异备份的类比:

我有一个 Excel 文件,单元格中有一些数据。

在第 1 天,我制作了该文件的副本并将其存储在其他地方(“完整备份”)。

在第 2 天,我查看该文件并将其与我在第 1 天制作的备份副本进行比较,并记下所有已更改的单元格及其新值(“差异备份”)。我没有注意到对单元格所做的每一个更改,只注意到它的最终值是什么。如果单元格 A1 以“Alfred”开头,改为“Betty”、“Charlie”,然后是“Dave”,我只会注意到“A1 现在是 Dave”。

在第 3 天,我再次将当前文件与备份文件进行比较并注意更改(另一个“差异备份”与第 2 天具有相同的基础)。同样,只注意观察时每个单元格的最终值,而不是单元格一整天的所有值。

在第 4 天,我再次比较并再次注意变化。继续使用单元格 A1,现在它显示“Sarah”,即使它全天有 10 个其他名字,我只注意到“现在 A1 是 Sarah”。

第 5 天,我的文件搞砸了;因此,我查看了我在第 1 天制作的备份副本,然后查看了第 4 天记录的最终状态,然后将记录的更改应用于备份副本,现在我将文件“恢复”到第 4 天的状态因此,我查看了第 1 天所做的备份,看到第 4 天单元格 A1 以“Sarah”结尾,并将备份单元格 A1 更改为“Sarah”。

如果我在第 2 天制作了文件的另一个备份副本(“完整”),为什么会如此重要?为什么仍然不能将第 3 天或第 4 天的文件与第 1 天制作的副本进行比较(阅读,“对其进行差异备份”)?据我了解,SQL Server 会要求我将(在进行另一次差异备份时)与第 2 天(如果已进行)进行的完整备份进行比较——别无选择。

Han*_*non 14

差异备份使用所谓的差异更改映射来构建自上次完整备份以来已修改的页面列表。此列表是一个“差异”列表,因此是备份类型的名称,也是备份只能在关联的完整备份之上恢复的原因。

执行完整备份会重置差异更改映射。从那时起,任何修改过的页面都会记录在地图中。如果您随后采用差异,则该备份仅包含自上次完整备份以来已修改并记录在映射中的页面。

在您的类比中,作为整个还原过程基础的两个完整备份可能具有不同的内容,因此具有不同的差异映射。如果基于第一个备份而不是第二个备份还原差异,则数据库可能会损坏。事实上,SQL Server 会阻止对差异备份的还原,除了它所基于的原始完整备份之外的任何内容。

当您要求 SQL Server 进行差异备份时,差异的唯一“基础”是差异备份开始时数据库中存在的单个差异更改映射。这就是您不能为差异备份指定基础的原因。


回应@MartinSmith 的评论 - 您可以使用COPY_ONLY备份来恢复多个完整备份的差异备份。考虑以下场景:

  1. BACKUP DATABASE xyz TO DISK = 'path_to_backup.bak';
  2. BACKUP DATABASE xyz TO DISK = 'path_to_backup_2.bak' WITH COPY_ONLY;
  3. BACKUP DATABASE xyz TO DISK = 'path_to_backup_3.bak' WITH COPY_ONLY;
  4. BACKUP DATABASE xyz TO DISK = 'path_to_backup_4.bak' WITH COPY_ONLY;
  5. BACKUP DATABASE xyz TO DISK = 'path_to_backup_diff.bak' WITH DIFFERENTIAL;

步骤 5 中的差异备份应该能够通过步骤 1 到 4 中的任何备份进行恢复,因为差异更改映射仅在步骤 1 中的完整备份发生时才被清除。COPY_ONLY步骤 2、3 和 4 中的备份不会重置更改映射。由于差异更改映射累积了自完整备份以来所做的更改,因此每个连续COPY_ONLY备份都包含足够的信息,以便差异备份能够针对前 4 个备份中的任何一个进行工作。

尽管它看起来应该可行,但实际上,在 copy_only 备份之上恢复差异会导致以下错误:

消息 3136,级别 16,状态 1,第 1 行
此差异备份无法还原,因为数据库尚未还原到正确的早期状态。
消息 3013,级别 16,状态 1,第 1 行
RESTORE DATABASE 异常终止。

我创建了一个 SQL Server 2012 平台 repro 来测试差异和 copy_only 还原,并将文件保存在gist.github.com 上- 警告脚本将删除任何命名RestoreTest为第一步的数据库。


usr*_*usr 5

您想要的功能原则上可以存在。当前的数据库结构效率不高(请参阅 Max Vernon 的回答)。SQL Server 必须要么维护一组差异映射,要么将当前数据库内容与您指定为基础的完整备份进行比较。

有些应用程序可以对大文件进行重复数据删除。您可以进行两次完整备份,实际上只会存储更改的数据。这就像自定义基础的差异。exdupe例如可以做到这一点。

这样做的好处是它可以与任何一组备份文件一起使用。事实上,从第三个完整备份文件开始,您只需支付增量(而非差异)空间使用费。空间使用量是与上一个备份文件(不是第一个)的差异。重复数据删除存储具有类似的行为。

为什么你描述的功能不存在?每个功能都会消耗预算,导致其他功能不存在。显然,这在优先级列表中还远远不够。我不确定它有什么好处。使用自定义基础似乎是一个相当深奥的要求。