SQL Server 2008 R2 使用事务日志还原 COPY_ONLY 完整备份

dv1*_*10t 12 sql-server-2008 backup transaction-log

在做了一些研究之后,我似乎无法找到这个问题的答案。

背景 我正在尝试设置一个符合以下三个要求的备份计划:

  1. 备份的可靠性,每晚进行完整备份
  2. 可以从中恢复的事务日志备份
  3. 使用的磁盘空间少
  4. 备份必须可在本地访问以供审计工具使用

因此,为了满足这些需求,我正在考虑每周进行完整备份、每天进行差异备份和每小时进行交易。然后每天晚上都会运行一个 copy_only 备份,可以将其运送到异地,这个备份完成后日志链不会被破坏,并且我们在异地拥有可靠的夜间完整备份,而不必占用太多本地磁盘空间。

问题 是否可以从copy_only 备份恢复,然后恢复事务日志。

让我举个例子,让你知道我在说什么。

使用下面的列表,我想知道是否可以恢复 FullbackupCOPY_ONLYC.bak 然后是 TransactionbackupG.trn、TransactionbackupH.trn、最后是 TransactionbackupI.trn

> ---List of Backups---   
FullbackupA.bak 01/01/2013 00:00:00   
>  DifferntialbackupA.bak 02/01/2013 00:00:00 
FullbackupCOPY_ONLYA.bak 02/01/2013 00:00:00
>     TransactionbackupA.trn 02/01/2013 01:00:00
>     TransactionbackupB.trn 02/01/2013 02:00:00
>     TransactionbackupC.trn 02/01/2013 03:00:00
>  DifferntialbackupB.bak 03/01/2013 00:00:00 
FullbackupCOPY_ONLYB.bak 03/01/2013 00:00:00
>     TransactionbackupD.trn 03/01/2013 01:00:00
>     TransactionbackupE.trn 03/01/2013 02:00:00
>     TransactionbackupF.trn 03/01/2013 03:00:00
>  DifferntialbackupC.bak 04/01/2013 00:00:00 
FullbackupCOPY_ONLYC.bak 04/01/2013 00:00:00
>     TransactionbackupG.trn 04/01/2013 01:00:00
>     TransactionbackupH.trn 04/01/2013 02:00:00
>     TransactionbackupI.trn 04/01/2013 03:00:00
Run Code Online (Sandbox Code Playgroud)

也许整个设置不合理我对 SQL Server 还很陌生,并且正在努力学习。任何建议/帮助将不胜感激。

Seb*_*ine 15

SQL Server 2008 中的完整备份不会破坏日志链。它只重置差异 base-lsn。

您还可以在仅从副本恢复后恢复日志备份。以下脚本演示了:

CREATE DATABASE BakTst13;
GO
ALTER DATABASE BakTst13 SET RECOVERY FULL;
GO
USE BakTst13;
GO
CREATE TABLE dbo.tst(id INT IDENTITY(1,1));
GO
INSERT INTO dbo.tst DEFAULT VALUES
GO 10
GO
BACKUP DATABASE BakTst13 
TO DISK = 'BakTst13_Full_1' WITH INIT,FORMAT;
GO
INSERT INTO dbo.tst DEFAULT VALUES
GO 10
GO
BACKUP LOG BakTst13 
TO DISK = 'BakTst13_Log_1' WITH INIT,FORMAT;
GO
INSERT INTO dbo.tst DEFAULT VALUES
GO 10
GO
BACKUP DATABASE BakTst13 
TO DISK = 'BakTst13_Full_2' WITH INIT,FORMAT;
GO
INSERT INTO dbo.tst DEFAULT VALUES
GO 10
GO
BACKUP DATABASE BakTst13 
TO DISK = 'BakTst13_Full_C' WITH COPY_ONLY,INIT,FORMAT;
GO
INSERT INTO dbo.tst DEFAULT VALUES
GO 10
GO
BACKUP LOG BakTst13 
TO DISK = 'BakTst13_Log_2' WITH INIT,FORMAT;
GO
USE tempdb;
GO
DROP DATABASE BakTst13;
GO
RESTORE DATABASE BakTst13 FROM DISK='BakTst13_Full_1' WITH NORECOVERY;
RESTORE LOG BakTst13 FROM DISK='BakTst13_Log_1' WITH NORECOVERY;
RESTORE LOG BakTst13 FROM DISK='BakTst13_Log_2' WITH RECOVERY;
GO
SELECT * FROM BakTst13.dbo.tst;
GO
DROP DATABASE BakTst13;
GO
RESTORE DATABASE BakTst13 FROM DISK='BakTst13_Full_C' WITH NORECOVERY;
RESTORE LOG BakTst13 FROM DISK='BakTst13_Log_2' WITH RECOVERY;
GO
SELECT * FROM BakTst13.dbo.tst;
GO
DROP DATABASE BakTst13;
Run Code Online (Sandbox Code Playgroud)

它创建一个数据库和一个表,并向该表中插入 50 行。在这些插入之间按以下顺序进行多个备份:

  1. 满的
  2. 日志
  3. 满的
  4. 完整副本_仅
  5. 日志

接下来,数据库将被删除和恢复,如下所示:

  1. 第一满
  2. 第一个日志
  3. 第二个日志

下图SELECT说明恢复成功。

这表明无论是COP_ONLY完整备份还是正常的完整备份都不会破坏日志链。

然后数据库再次删除并恢复如下:

  1. Copy_Only 完整
  2. 第二个日志

之后SELECT再次显示成功。

这表明您可以使用COPY_ONLY完整备份作为日志还原的基础。

差异测试

我也创建了一个DIFFERENTIAL版本:

CREATE DATABASE BakTst13;
GO
ALTER DATABASE BakTst13 SET RECOVERY FULL;
GO
USE BakTst13;
GO
CREATE TABLE dbo.tst(id INT IDENTITY(1,1));
GO
INSERT INTO dbo.tst DEFAULT VALUES
GO 10
GO
BACKUP DATABASE BakTst13 
TO DISK = 'BakTst13_Full_1' WITH INIT,FORMAT;
GO
INSERT INTO dbo.tst DEFAULT VALUES
GO 10
GO
BACKUP DATABASE BakTst13 
TO DISK = 'BakTst13_Diff_1' WITH DIFFERENTIAL,INIT,FORMAT;
GO
INSERT INTO dbo.tst DEFAULT VALUES
GO 10
GO
BACKUP DATABASE BakTst13 
TO DISK = 'BakTst13_Full_2' WITH INIT,FORMAT;
GO
INSERT INTO dbo.tst DEFAULT VALUES
GO 10
GO
BACKUP DATABASE BakTst13 
TO DISK = 'BakTst13_Diff_2' WITH DIFFERENTIAL,INIT,FORMAT;
GO
INSERT INTO dbo.tst DEFAULT VALUES
GO 10
GO
BACKUP DATABASE BakTst13 
TO DISK = 'BakTst13_Full_C' WITH COPY_ONLY,INIT,FORMAT;
GO
INSERT INTO dbo.tst DEFAULT VALUES
GO 10
GO
BACKUP DATABASE BakTst13 
TO DISK = 'BakTst13_Diff_3' WITH DIFFERENTIAL,INIT,FORMAT;
GO
USE tempdb;
GO
DROP DATABASE BakTst13;
GO
RAISERROR('------> Starting restore F1, D1, D2',0,1)WITH NOWAIT;
RESTORE DATABASE BakTst13 FROM DISK='BakTst13_Full_1' WITH NORECOVERY; 
RESTORE DATABASE BakTst13 FROM DISK='BakTst13_Diff_1' WITH NORECOVERY;
RESTORE DATABASE BakTst13 FROM DISK='BakTst13_Diff_2' WITH NORECOVERY;--<--Fails!
GO
DROP DATABASE BakTst13;
GO
RAISERROR('------> Starting restore FC, D3',0,1)WITH NOWAIT;
RESTORE DATABASE BakTst13 FROM DISK='BakTst13_Full_C' WITH NORECOVERY;
RESTORE DATABASE BakTst13 FROM DISK='BakTst13_Diff_3' WITH NORECOVERY;--<--Fails!
GO
DROP DATABASE BakTst13;
GO
RAISERROR('------> Starting restore F2, D2, D3',0,1)WITH NOWAIT;
RESTORE DATABASE BakTst13 FROM DISK='BakTst13_Full_2' WITH NORECOVERY; 
RESTORE DATABASE BakTst13 FROM DISK='BakTst13_Diff_2' WITH NORECOVERY;
RESTORE DATABASE BakTst13 FROM DISK='BakTst13_Diff_3' WITH RECOVERY;
GO
SELECT * FROM BakTst13.dbo.tst;
GO
DROP DATABASE BakTst13;
Run Code Online (Sandbox Code Playgroud)

这将按以下顺序进行备份:

  1. 第一满
  2. 第一差速器
  3. 第二个完整
  4. 第二差速器
  5. Copy_Only 差异
  6. 第三差速器

然后它尝试这个恢复路线:

  1. 第一满
  2. 第一差速器
  3. 第二差速器

第 3 步失败并显示此错误:

Msg 3136, Level 16, State 1, Line 4
This differential backup cannot be restored because the database has not been restored to the correct earlier state.
Run Code Online (Sandbox Code Playgroud)

这表明正常的完整备份会破坏差异链。

接下来删除数据库并尝试此还原流程:

  1. Copy_Only 完整
  2. 第三差速器

第 2 步失败,并出现与上述第 3 步相同的错误。这表明仅复制备份不能用作差异还原的基础。

然后再次删除数据库并执行以下还原:

  1. 第二个完整
  2. 第二差速器
  3. 第三差速器

下面的select证明这次恢复成功了。这表明COPY_ONLY完整备份不会中断差异链。