“伪简单 SQL Server 恢复”是术语和场景,我刚刚在(现已删除)新问题SQL Server Truncates Transaction Logs with Copy Only Backups的评论中了解到
我去了Rajendra Gupta 于 2019 年 10 月 7 日发表的 Pseudo-Simple SQL Server Recovery Model帖子,并在那里使用了一些代码,我自己的一些代码做了一些测试。
创建数据库(Rajendra 的代码)
CREATE DATABASE RecoveryModel;
并验证它是否完整(Rajendra 的代码)
SELECT name,
recovery_model_desc
FROM sys.databases
WHERE name = 'RecoveryModel';
做一些工作(Rajendra 的代码,稍作修改)
Use RecoveryModel
CREATE TABLE test(id INT);
GO
INSERT INTO test
VALUES(1);
GO 5000
查看使用了多少日志空间(我的代码)
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
我们发现有日志正在填充。再次运行工作并检查大小,日志增长,不足为奇。
尝试运行 t-log(我的代码)
BACKUP LOG [RecoveryModel] TO
DISK = N'E:\SQLBackups\RecoveryModel.trn' WITH NOFORMAT, NOINIT, SKIP, NOREWIND, NOUNLOAD
GO
它失败并显示消息:
消息 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
它运行良好,检查日志空间并没有缩小。再运行几次工作负载,日志空间继续增长。运行 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
它就像 t_log 一样失败
消息 3035,级别 16,状态 1,第 13 行无法为数据库“RecoveryModel”执行差异备份,因为当前数据库备份不存在。通过重新发出 BACKUP DATABASE 执行完整的数据库备份,省略 WITH DIFFERENTIAL 选项。
那么关于这个的“伪简单”是什么?日志增长,t-log 和差异备份失败。您有一个处于完全恢复状态的数据库,没有完全备份。
编辑它看起来像我的构建中的服务器特定的东西导致结果与其他人看到的不同。我接受了乔希的回答。
请参阅数据库恢复模型专家 Paul Randal 的这篇文章:新脚本:该数据库真的处于完全恢复模式吗?
特别是这句话证实了“伪简单”恢复模型的行为:
Kimberly Tripp 在这里详细阐述了该主题:数据库维护最佳实践第三部分 – 事务日志维护
我不完全同意您关于在完整备份之前在完整恢复模型中事务日志备份失败的说法“这一点都不简单”。这就像 SIMPLE 模型(不允许日志备份)。错误消息是不同的,因为它试图告诉最终用户如何解决问题。
我在 SQL Server 2017 上尝试了您的测试,并且运行仅复制备份始终触发内部
CHECKPOINT
并清除日志(PercentFree
日志文件增加)。在初始运行时,
PercentFree
_log 文件中的65.04
.我运行了仅复制备份,然后
PercentFree
跳转到88.68
.我通过以下扩展事件会话确认
CHECKPOINT
此时也运行了 a。伪简单意味着完全恢复模型中的数据库在进行第一次完全备份之前将表现得好像它处于简单恢复模型中一样(记录备份的最后一个日志序列号)。
换句话说,处于完全恢复模式的数据库需要有效的备份链,而有效的备份链需要完全备份才能启动。然后,您可以根据自己的需要并行执行日志和差异备份,每个备份都基于此初始完整备份。
正如您在运行的脚本中看到的那样,在您运行完整(仅复制)备份之前没有建立备份链。一旦运行,您就启动了一个备份链,但是因为您进行了仅复制备份,所以您混淆了事情。
差异备份是减少需要还原到特定时间点的日志备份数量的捷径。它们依赖于不是 的完整备份,
COPY ONLY
因为仅复制备份不会重置用于跟踪自上次完整备份以来修改了哪些扩展区的差异位图。如果您进行了标准完整备份(没有
COPY ONLY
),您的差异将成功,并且数据库将不再处于伪简单状态。更令人困惑的是,如果没有完整(非仅复制)备份来启动链,在简单恢复模型中的数据库上差异备份也会失败。我(关于问题的 OP)不知道为什么“伪简单 SQL Server 恢复”按照多个帖子中的定义工作,但我没有通过这些测试在我的系统上看到它。
在研究阶段,我将数据库放入
SIMPLE
并重新创建了测试,使用的日志文件大小与它相同FULL
,这表明控制事务持久性但进一步测试排除了这一点。经过更多的研究和测试,我想通了!(感谢帮助我解决问题的同事。)
COPY ONLY
备份之前,我运行了 3 到 5 次测试工作负载(6 到 10MB 的日志)。COPY ONLY
并使用空间下降到 2MB,第一个 VLF 返回状态 0,第二个 VLF 保持最后 2MB.
谈论 VLF 的相关信息:VLF太多 - 我如何截断它们?