SQL Server 2022 为事务日志文件增长事件引入了即时文件初始化。在What's New in 2022 page中,Microsoft 指出:
通常,事务日志文件无法从即时文件初始化 (IFI) 中受益。从 SQL Server 2022 (16.x)(所有版本)和 Azure SQL 数据库开始,即时文件初始化可以使高达 64 MB 的事务日志增长事件受益。新数据库的默认自动增长大小增量为 64 MB。大于 64 MB 的事务日志文件自动增长事件无法从即时文件初始化中受益。
为了对此进行测试,我尝试以不同的大小(比如 50 和 70MB)反复增加日志文件,但是......它们都不是即时的。
DROP DATABASE LogGrowthTest;
GO
CREATE DATABASE [LogGrowthTest]
CONTAINMENT = NONE
ON PRIMARY
( NAME = N'LogGrowthTest', FILENAME = N'Z:\MSSQL\Data\LogGrowthTest.mdf',
SIZE = 8192KB , FILEGROWTH = 60000KB )
LOG ON
( NAME = N'LogGrowthTest_log', FILENAME = N'Z:\MSSQL\Data\LogGrowthTest_log.ldf' ,
SIZE = 8192KB , FILEGROWTH = 60000KB )
GO
DECLARE @TestStartTime DATETIME2 = GETDATE(), @i INT = 1,
@StringStarter NVARCHAR(4000) = N'ALTER DATABASE [LogGrowthTest] MODIFY FILE ( NAME = N''LogGrowthTest_log'', SIZE = ',
@StringToExec NVARCHAR(4000);
WHILE @i < 101
BEGIN
/* CHANGE THE 63 IN THE BELOW LINE TO CHANGE FILE GROWTH SIZE: */
SET @StringToExec = @StringStarter + CAST((@i * 63) AS NVARCHAR(10)) + N'MB );';
PRINT(@StringToExec)
EXEC(@StringToExec);
SET @i = @i + 1;
END
SELECT DATEDIFF(millisecond,@TestStartTime, GETDATE()) AS TestDurationSeconds
GO
我尝试了 63MB、65MB,但似乎没有太大区别 - 100 个增长事件的测试大约需要 15-16 秒。
所以问题是,即时文件初始化是否不适用于手动日志文件增长,即使是小文件?只有自动增长事件?(我还无法证明它也适用于自动增长事件。)
是的,它确实。
我在 SQL Server 2019 和 SQL Server 2022 上尝试了以下操作(在安装过程中启用了 IFI)
对于 SQL Server 2019,我可以看到整个新分配的文件部分以 8MB 块的形式写入(从长度和偏移量来看)
ProcMon 中的堆栈显示此活动正在文件清零时发生
2022年无对应段
在 2019 年的情况下(21:30:54.8866621 到 21:30:54.9330198),第一次和最后一次 procmon 条目之间经过的时间是 46 毫秒,在 2022 年的情况下是 7.9 毫秒(21:31:54.8078691 到 21:31:54.8157769)。
SET STATISTICS TIME ON
我也看到了通过输出报告的类似时间差异。两者都在写入同一张笔记本电脑光盘(从上面的内容中,敏锐的眼睛可能会注意到我不小心将我的 2022 实例命名为 20222)。
我对为什么循环表现如此糟糕很感兴趣。似乎只有第一个条目真正受益于 IFI。
当我将以下内容添加到上面的代码时......
第二次增长需要更长的时间并写入更多的文件(包括之前未初始化的部分)
这不是由于文件清零,也不是我在 SQL Server 2019 实例中看到的东西,因此似乎是额外的工作,可能与此功能相关,也可能不相关。
令人恼火的是,出于某种原因,ProcMon 只向我显示一个空白选项卡,而不是突出显示的 WriteFile 的调用堆栈,但 Windows 性能记录器将暗示这是在
sqlmin.dll!SQLServerLogMgr::FormatVirtualLogFile
(这与 Paul 的回答相关)使用以下方法在我的本地 2022 实例上确认:
全局跟踪标志 3004(显示即时文件初始化详细信息)和 1810(增长事件详细信息)的输出也启用了 3604 以将输出定向到 SSMS 消息选项卡:
跟踪标志 1810 在其格式字符串(
%l64d
而不是%I64d
)中有一个错误。如果您不自己解决这个问题,您可以使用扩展事件database_file_size_change
或modify_file_operation
替代来监控增长。据我所知,没有监控 IFI 的事件,因此您需要 3004 来处理该部分。sys.dm_db_log_info
在日志增长之前:之后:
Noticed each growth added a single virtual log file (VLF).
The new feature can be disabled with global trace flag 1837. With that set, the output changes to:
Resetting to the same starting point and running the ten growth script again, the log DMV shows:
请注意,大多数 64MB 增长导致 4 x 16MB VLF。