伪简单 SQL Server 恢复是真的吗?

Jam*_*ins 4 sql-server backup terminology

“伪简单 SQL Server 恢复”是术语和场景,我刚刚在(现已删除)新问题的评论中了解到SQL Server 使用仅复制备份截断事务日志

我转到了 Rajendra Gupta 于 2019 年 10 月 7 日发布的Pseudo-Simple SQL Server Recovery Model帖子并使用了那里的一些代码和我自己的一些代码进行了一些测试。

创建数据库(Rajendra 的代码)

CREATE DATABASE RecoveryModel;
Run Code Online (Sandbox Code Playgroud)

并验证它是完整的(Rajendra 的代码)

SELECT name, 
    recovery_model_desc
FROM sys.databases
WHERE name = 'RecoveryModel';
Run Code Online (Sandbox Code Playgroud)

做一些工作(Rajendra 的代码,稍作修改)

Use RecoveryModel
CREATE TABLE test(id INT);
GO 
INSERT INTO test
VALUES(1);
GO 5000
Run Code Online (Sandbox Code Playgroud)

查看使用了多少日志空间(我的代码)

select file_id
, type_desc
, name
, substring([physical_name],1,3) AS [Drive]
, physical_name
, state_desc
, size / 128 as 'AllocatedSizeMB'
, FILEPROPERTY([name],'SpaceUsed') /128 AS 'SpaceUsedMB'  --Addapted from https://sqlperformance.com/2014/12/io-subsystem/proactive-sql-server-health-checks-1
, (1- (FILEPROPERTY([name],'SpaceUsed') / CAST (size AS MONEY))) *100 AS 'PercentFree'
, growth / 128 as 'GrowthSettingMB'

 from sys.database_files
 order by type_desc Desc, name
Run Code Online (Sandbox Code Playgroud)

我们发现有日志正在填充。再次运行工作并检查大小,日志增长,这并不奇怪。

尝试运行 t-log(我的代码)

BACKUP LOG [RecoveryModel] TO  
DISK = N'E:\SQLBackups\RecoveryModel.trn' WITH NOFORMAT, NOINIT, SKIP, NOREWIND, NOUNLOAD 
GO
Run Code Online (Sandbox Code Playgroud)

它失败并显示以下消息:

消息 4214,级别 16,状态 1,第 8 行

无法执行 BACKUP LOG,因为当前没有数据库备份。

消息 3013,级别 16,状态 1,第 8 行

BACKUP LOG 异常终止。

如果您尝试在简单恢复中备份数据库,那么没有什么比这更简单的了。你收到消息

消息 4208,级别 16,状态 1,第 19 行

当恢复模式为 SIMPLE 时,不允许使用 BACKUP LOG 语句。使用 BACKUP DATABASE 或使用 ALTER DATABASE 更改恢复模型。

仅运行副本备份(我的代码)

BACKUP DATABASE [RecoveryModel] TO  
DISK = N'E:\SQLBackups\RecoveryModel.bak' WITH NOFORMAT, INIT, COPY_ONLY,  
NAME = N'RecoveryModel-Full Database Backup', SKIP, NOREWIND, NOUNLOAD
GO
Run Code Online (Sandbox Code Playgroud)

它运行良好,检查日志空间并没有缩小。再运行几次工作负载,日志空间继续增长。运行 t-log 备份,它继续失败。

运行差异备份(我的代码)

BACKUP DATABASE [RecoveryModel] TO  
DISK = N'E:\SQLBackups\RecoveryModel.dif' WITH  DIFFERENTIAL , NOFORMAT, NOINIT,  
NAME = N'RecoveryModel-Diff Database Backup', SKIP, NOREWIND, NOUNLOAD
GO
Run Code Online (Sandbox Code Playgroud)

它就像 t_log 一样失败

消息 3035,级别 16,状态 1,第 13 行无法对数据库“RecoveryModel”执行差异备份,因为当前数据库备份不存在。通过重新发出 BACKUP DATABASE 执行完整的数据库备份,省略 WITH DIFFERENTIAL 选项。

那么什么是“伪简单”呢?日志增长,t-log 和差异备份失败。您有一个完全恢复的数据库,没有完全备份。

编辑它看起来我的构建中的服务器有一些特定的东西导致结果与其他人看到的不同。我已经接受了乔希的回答。

Jos*_*ell 5

请参阅数据库恢复模型专家 Paul Randal 的这篇文章:新脚本:该数据库真的处于完全恢复模式吗?

特别是这句话证实了“伪简单”恢复模型的行为:

...当您将数据库切换到完全恢复模式时,它实际上就像处于简单恢复模式一样,直到建立日志备份链(这通常称为“伪简单”)。

Kimberly Tripp 在此处详细介绍了该主题:数据库维护最佳实践第三部分 – 事务日志维护

这意味着一旦 SQL Server 知道它不再需要它们,它就会自动从事务日志中清除非活动记录。不再需要将它们存储在日志中,因为没有人使用日志

我不完全同意你关于在完全备份之前完全恢复模型中事务日志备份失败的陈述“没有什么比这更简单”。这就像 SIMPLE 模型(不允许日志备份)。错误消息是不同的,因为它试图告诉最终用户如何解决问题。

我在 SQL Server 2017 上尝试了您的测试,并且运行仅复制备份始终会触发内部CHECKPOINT并清除日志(PercentFree日志文件增加)。

在初始运行时,PercentFree_log 文件中的65.04.
我运行了仅复制备份,然后PercentFree跳转到88.68.

我通过以下扩展事件会话确认CHECKPOINT此时也运行了 a 。

CREATE EVENT SESSION [checkpointage] ON SERVER 
ADD EVENT sqlserver.checkpoint_begin(
    ACTION(sqlserver.database_id)),
ADD EVENT sqlserver.checkpoint_end(
    ACTION(sqlserver.database_id))
ADD TARGET package0.event_file(SET filename=N'checkpointage')
WITH (STARTUP_STATE=OFF)
GO
Run Code Online (Sandbox Code Playgroud)