SQL 服务器 初始备份还原有效,其余无效

SQL Server The initial backup restore works, the rest don't

我正在尝试备份和恢复 Sql Server 2014 中的数据库。 初始备份还原有效。 但是当我对数据库进行一些更改并重复 backup/reload 过程时 我得到丢失最新更改的第一个备份的数据。 下面是一个说明我面临的问题的脚本

CREATE DATABASE sample;

CREATE TABLE list (
    id INT, 
    name VARCHAR(50)
);

--first record is inserted

BACKUP DATABASE sample to DISK='D:\Backup\sample.bak';

truncate table list;


GO
USE master;
GO
ALTER DATABASE sample
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE;
GO
RESTORE DATABASE sample FROM DISK='D:\Backup\sample.bak' with REPLACE;
GO
ALTER DATABASE sample
SET MULTI_USER;
GO


--restored database contains one record
use sample;
select * from list;

--second record is inserted
insert into list values(2,'item_2');
select * from list;


BACKUP DATABASE sample to DISK='D:\Backup\sample.bak';

GO
USE master;
GO
ALTER DATABASE sample
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE;
GO
RESTORE DATABASE sample FROM DISK='D:\Backup\sample.bak' with REPLACE;
GO
ALTER DATABASE sample
SET MULTI_USER;
GO

--restored database STILL contains one record
use sample;
select * from list;

当你使用同一个文件在其中做backup,而没有在备份命令中指定with init时,新的备份被追加到最后这个文件的。这意味着在第二次备份后,您将在同一个备份文件中有 2 个备份。

当您 restore 来自包含超过 1 个 backup 的文件时,您应该指定 with file 和此文件中备份的名称或编号,否则第一个 backup 将被 deafult

使用

问题是您的 backup database sample to disk='...' 语句默认将新备份附加到备份设备(备份文件)。结果,您在备份文件中存储了多个备份。 进行还原时,您正在还原第一个备份。

解决问题,可以通过"WITH INIT"参数指定覆盖备份文件的内容:

BACKUP DATABASE sample to DISK='D:\Backup\sample.bak' WITH INIT;

可以找到更多文档,例如。 here

BACKUP 语句中使用 WITH INIT 重新初始化备份文件。

在我的 Sandbox 实例上,如下:

CREATE DATABASE [sample];
GO

USE [sample];
GO
CREATE TABLE dbo.list (i int,
                       s varchar(6));
GO

USE master;
GO

BACKUP DATABASE [sample]
    TO  DISK = 'C:\Program Files\Microsoft SQL Server\MSSQL11.SANDBOX\MSSQL\Backup\sample.bak'
    WITH INIT;
GO
USE [sample];
GO
TRUNCATE TABLE dbo.list;

GO
USE master;
GO
ALTER DATABASE [sample] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
RESTORE DATABASE [sample]
    FROM DISK = 'C:\Program Files\Microsoft SQL Server\MSSQL11.SANDBOX\MSSQL\Backup\sample.bak'
    WITH REPLACE;
GO
ALTER DATABASE [sample] SET MULTI_USER;
GO


--restored database contains no rows (none have been inserted yet
USE [sample];
GO
SELECT *
FROM dbo.list;

--first row is inserted
INSERT INTO dbo.list
VALUES (2, 'item_2');
SELECT *
FROM dbo.list;
GO
USE master;
GO
BACKUP DATABASE [sample]
    TO  DISK = 'C:\Program Files\Microsoft SQL Server\MSSQL11.SANDBOX\MSSQL\Backup\sample.bak'
    WITH INIT;

GO
ALTER DATABASE [sample] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
RESTORE DATABASE [sample]
    FROM DISK = 'C:\Program Files\Microsoft SQL Server\MSSQL11.SANDBOX\MSSQL\Backup\sample.bak'
    WITH REPLACE;
GO
ALTER DATABASE [sample] SET MULTI_USER;
GO

--restored database STILL contains one record
USE [sample];
SELECT *
FROM dbo.list;
GO

USE master;
GO

DROP DATABASE [sample];

创建以下数据集:

如您所见,现在最后的 SELECT 保留了新行。

否则,如果您在 BACKUP 过程中省略 INIT,则需要在第二个 RESTORE 中提供位置。在这种情况下,它将是文件 2:

RESTORE DATABASE [sample]
    FROM DISK = 'C:\Program Files\Microsoft SQL Server\MSSQL11.SANDBOX\MSSQL\Backup\sample.bak'
    WITH REPLACE, FILE = 2;

动画 GIF 演示(您可能希望在新的 window 中打开):