差异备份问题 - 为什么?这可能吗?

iKn*_*ing 13 sql-server backup restore

我使用的是 SQL Server 2014,情况是这样的:

  • 我有服务器 A 和服务器 B。
  • 在服务器 A 上处理隔夜 ETL。
  • 加载过程完成后,数据库 X 得到备份(使用CHECKSUMRESTORE VERIFYONLY以确保可靠性),然后发送到服务器 B。
  • 服务器 B 接收bak文件,然后在那里恢复数据库。

我想使用差异备份策略,以便:

  1. 完整备份仅在星期六进行,
    即星期六在服务器 A 上进行完整备份 -> 运送到服务器 B -> 在服务器 B 上恢复完整备份

  2. 剩下的日子将是差异备份,
    即服务器 A 上的差异备份 -> 运送到服务器 B -> 在服务器 B 上恢复差异备份

我试过了,但出现错误,说:

无法恢复日志或差异备份,因为没有文件准备好前滚。

不知道为什么。我检查sys.database_files了服务器 A 和服务器 B,我可以看到differential_Base_LSNdifferential_base_GUID是相同的。任何地方/还有什么要检查的吗?

顺便说一下,在上面的第 2 步中,当我在服务器 B 上恢复差异备份时,是否每次都需要同时恢复完整备份 + 差异备份?

我只恢复了差异备份WITH RECOVERY(并收到了错误消息),因为前一天已经恢复了完整备份。

澄清一下:是的,我希望服务器 B 上的数据库在差异之间可读。我怎样才能解决这个问题?是我每晚RESTORE FULL (WITH NORECOVERY)+RESTORE DIFF (WITH RECOVERY)组合序列的唯一选择吗?

任何指导将不胜感激。

Eri*_*ing 15

你并不需要乱用RECOVERYNORECOVERY在这里,所有你需要的是STANDBY选项。这是有关如何使用它的快速演示。

创建一个数据库,将其设置为简单恢复,并创建一个表。

插入数据,取一些差异。

好玩吧?

USE master;

/*Create a dummy database*/
CREATE DATABASE DiffRestoreTest

/*We simple now*/
ALTER DATABASE DiffRestoreTest SET RECOVERY SIMPLE

/*Context is everything*/
USE DiffRestoreTest

/*If nothing changes, do we even need a diff backup?*/
CREATE TABLE dbo.t1 (Id INT)

/*Take a full backup, dummy*/
BACKUP DATABASE DiffRestoreTest 
TO DISK = 'F:\Backup\DRT_FULL.bak' 
WITH INIT, FORMAT, COMPRESSION

/*Make a change*/
INSERT dbo.t1 (Id )
VALUES ( 1 )

/*Take a differential backup*/
BACKUP DATABASE DiffRestoreTest 
TO DISK = 'F:\Backup\DRT_DIFF_1.bak' 
WITH INIT, FORMAT, COMPRESSION, DIFFERENTIAL

/*Make another change*/
INSERT dbo.t1 (Id )
VALUES ( 2 )

/*Take another diff backup*/
BACKUP DATABASE DiffRestoreTest  
TO DISK = 'F:\Backup\DRT_DIFF_2.bak' 
WITH INIT, FORMAT, COMPRESSION, DIFFERENTIAL

/*Make another change*/
INSERT dbo.t1 (Id )
VALUES ( 3 )

/*Take another diff backup*/
BACKUP DATABASE DiffRestoreTest 
TO DISK = 'F:\Backup\DRT_DIFF_3.bak' 
WITH INIT, FORMAT, COMPRESSION, DIFFERENTIAL
Run Code Online (Sandbox Code Playgroud)

是的,我撒谎了。这就是无聊的部分。

您可以在STANDBY以下位置恢复完整备份:

/*Exit stage left*/
USE master

/*Restore the full backup*/
RESTORE DATABASE DiffRestoreTest
FROM DISK = 'F:\Backup\DRT_FULL.bak' 
WITH REPLACE, STANDBY = 'F:\Backup\DRT_STANDBY.tuf'
Run Code Online (Sandbox Code Playgroud)

您可以按顺序恢复差异STANDBY

/*Square one*/
RESTORE DATABASE DiffRestoreTest
FROM DISK = 'F:\Backup\DRT_DIFF_1.bak' 
WITH STANDBY = 'F:\Backup\DRT_STANDBY.tuf'

/*Square 2*/
RESTORE DATABASE DiffRestoreTest
FROM DISK = 'F:\Backup\DRT_DIFF_2.bak' 
WITH STANDBY = 'F:\Backup\DRT_STANDBY.tuf'

/*Square 3*/
RESTORE DATABASE DiffRestoreTest
FROM DISK = 'F:\Backup\DRT_DIFF_3.bak' 
WITH STANDBY = 'F:\Backup\DRT_STANDBY.tuf'
Run Code Online (Sandbox Code Playgroud)

与那些讨厌的日志文件不同的是,您也可以在恢复差异时跳过:

/*Restore the full backup*/
RESTORE DATABASE DiffRestoreTest
FROM DISK = 'F:\Backup\DRT_FULL.bak' 
WITH REPLACE, STANDBY = 'F:\Backup\DRT_STANDBY.tuf'

/*What happens if I try to jump the restores?*/
RESTORE DATABASE DiffRestoreTest
FROM DISK = 'F:\Backup\DRT_DIFF_3.bak' 
WITH STANDBY = 'F:\Backup\DRT_STANDBY.tuf'
Run Code Online (Sandbox Code Playgroud)

如果你想测试可读性,只需在恢复命令之间运行它。您应该看到 ID 随每个增加。如果你不这样做,你就做错了可怕的事情。

请记住,当您恢复文件时,它会将所有最终用户踢出数据库,并且不会等待他们的查询完成。

这也使数据库处于只读状态,不能在此处进行任何更改。

SELECT * 
FROM DiffRestoreTest.dbo.t1 AS t
Run Code Online (Sandbox Code Playgroud)

最后,清理自己。

/*Bring'er online, lad*/
RESTORE DATABASE DiffRestoreTest WITH RECOVERY

DROP DATABASE DiffRestoreTest
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!!