无法恢复(错误 3456)

Ned*_*ter 9 sql-server sql-server-2008-r2 recovery restore

我有一个不容易弄清楚的情况,我想我会在这个论坛上问其他人是否有建议。

我在 Windows Server 2008R2 Enterprise 上运行 SQL Server 2008 R2 Standard SP3。

一个数据库需要一些维护,事后我需要在另一台服务器上恢复。我使用 COPY_ONLY 和一组 4 个 tlog 备份完成了完整的数据库备份。

  1. 在开始之前,创建 tlogbackup1
  2. 更改FULLBULK_LOGGED恢复模式
  3. 添加新文件组
  4. 将文件添加到新文件组
  5. 将新文件组设置为默认值
  6. 选择到表中(在新文件组上)
  7. 删除原始表
  8. 删除原始文件
  9. 删除原始文件组
  10. 更改新表的名称以匹配原始表
  11. 更改新文件组的文件名以匹配原始文件组
  12. 更改目录中的文件名以匹配原始文件名
  13. 在操作系统级别更改文件名以匹配原始文件名
  14. 将默认文件组设置为原始文件组
  15. 使数据库在线
  16. 更改BULK_LOGGEDFULL恢复模式
  17. 完成所有步骤后,创建 tlogbackup2

由于还原服务器上的驱动器号更改,所有备份的还原必须使用 WITH MOVE。

恢复步骤:

RESTORE database SomeDB FROM DISK = 'D:\REPRO\SomeDB.bak'   
WITH 
MOVE 'SystemData' TO 'D:\SQLDATA\SomeDB.mdf'
,MOVE 'SystemDataPDS' TO 'D:\SqlData\SomeDB.ndf'
,MOVE 'SystemData_log' TO 'D:\SQLLogs\SomeDB.LDF'
,NORECOVERY
,stats = 1

RESTORE LOG SomeDB FROM DISK = 'D:\REPRO\tlogbackup1.trn'   
WITH 
MOVE 'SystemData' TO 'D:\SQLDATA\SomeDB.mdf'
,MOVE 'SystemDataPDS' TO 'D:\SqlData\SomeDB.ndf'
,MOVE 'SystemData_log' TO 'D:\SQLLogs\SomeDB.LDF'
,NORECOVERY
,stats = 1

RESTORE LOG SomeDB FROM DISK = 'D:\REPRO\tlogbackup2.trn'   
WITH 
MOVE 'SystemData' TO 'D:\SQLDATA\SomeDB.mdf'
,MOVE 'SystemDataPDS' TO 'D:\SqlData\SomeDB.ndf'
,MOVE 'SystemData_log' TO 'D:\SQLLogs\SomeDB.LDF'
,NORECOVERY
,stats = 1
Run Code Online (Sandbox Code Playgroud)

最终的 tlog 恢复达到 100%,然后失败并显示错误 3456:

为数据库“SomeDB”处理了 368 页,文件 1 上的文件“SystemData”。

为数据库“SomeDB”处理了 7656520 页,文件 1 上的文件“SystemDataPDS”。

为数据库“SomeDB”处理了 172430 页,文件 1 上的文件“SystemData_log”。

消息 3456,级别 16,状态 1,第 1 行
无法重做日志记录 (210388:123648:232),对于事务 ID (0:1016710921),页面 (4:8088),数据库“SomeDB”(数据库 ID 6) . 页:LSN = (0:0:1),类型 = 11。日志:OpCode = 4,上下文 11,PrevPageLSN:(210388:122007:1)。从数据库的备份还原,或修复数据库。消息 3013,级别 16,状态 1,第 1 行 RESTORE LOG 异常终止。

只是为了验证完整的 db 备份是否正常,我恢复了它 run CHECKDB,并且没有错误。

欢迎所有反馈。

提前致谢,

内德·奥特

Tho*_*ger 9

为了理解为什么会抛出错误 3456,我们需要退后一步,了解 SQL Server 如何处理恢复的这个角落。

当 SQL Server 正在重做操作时,并且该重做是页面修改,它会进行快速检查。在页头中,最终会有一个PageLSN,它表示已修改该页的最后一个 LSN,由该页记录。可以这样想,页面会跟踪对其进行修改的最后一个 LSN。这是PageLSN.

每次记录页面修改操作时,该日志记录都会包含一些 LSN。即,日志记录的 LSN(想想...当前 LSN),然后它具有所谓的上一页 LSNPrevPageLSN前进)。因此,当我们修改页面时,放入日志记录的数据片段之一是该页面指示的最后一个 LSN 是您修改该页面之前的内容

像这样想......你的车需要完成工作。机械师约翰在你的车上工作,在发动机舱它有一个小标签,机械师约翰写着“约翰最后在这辆车上工作”。然后下次你把车开到另一家商店时,机械师马克查看发动机舱,看到机械师约翰最后在这辆车上工作。在他的数据表上,他写下了这些信息。与 SQL Server 相同的想法。

这可能有点令人困惑,因此请查看下面有关连续页面修改的图像,以及PageLSNPrevPageLSN之间的关系:

在此处输入图片说明

让我们回过头来,因为当您需要在页面上重做操作(还原、恢复、HA 等)时,这一切都会发挥作用。当 SQL Server 需要重做页面操作时,它会进行完整性检查以查看PageLSN页面上的PrevPageLSN是否与日志记录包含的匹配。如果这不相等,那么您将看到错误 3456 被抛出。

PageLSN是否等于PrevPageLSN?不???停止并引发错误 3456...

让我们分析您的错误消息,其中包括如何:

无法重做日志记录 (210388:123648:232),事务 ID (0:1016710921),页面 (4:8088),数据库“SomeDB”(数据库 ID 6)。页:LSN = (0:0:1),类型 = 11。日志:OpCode = 4,上下文 11,PrevPageLSN:(210388:122007:1)。从数据库的备份还原,或修复数据库。消息 3013,级别 16,状态 1,第 1 行 RESTORE LOG 异常终止。

我已将导致错误的不等式的两条数据加粗。您可以看到我们的PageLSN0:0:1(在页面标题中找到),而我们的PrevPageLSN210388:122007:1(在尝试重做的日志记录中的数据中找到)。这些显然不相等,因此 err3456。

所以为了找出这个事件的原因,就是找出为什么这里存在差异。我们真的需要跟踪页面 4:8088 的生命周期,看看断开连接的地方。不幸的是,如果没有进一步的信息或实际的故障排除,除了向您提供此恢复操作的背景以及导致错误的原因之外,我无能为力。