有多少 VLF 可能是坏的

Beg*_*DBA 6 performance sql-server sql-server-2012

我有一个大小为 840 GB 的数据库,其中有 948 个 VLF。另一方面,有一个大小为 1.6 TB 的有 320 个 VLF。这是否表明具有大量 VLF 的较小数据库实际上是一个问题?另外我们如何确定该数字太大或在OK范围内。

请建议

Han*_*non 15

如果 VLF 的数量及其大小的组合意味着恢复过程将需要比您的恢复时间目标更长的持续时间,那么VLF计数只会成为恢复时间的问题。

没有单一数量的 VLF 是好是坏。通常,我将每个 VLF 保持在 512MB 以下,并将 VLF 的数量保持在 1,000 以下。

为了了解给定日志文件的实际恢复时间,您需要在测试环境中具有相同的硬件设置,并测试在活动事务运行时数据库已关闭的完整日志的恢复。如果您有一个包含数十万个 VLF 的数据库,请非常担心恢复时间。问我怎么知道。

您可以通过查看DBCC LOGINFO所需数据库的上下文来查看有关 VLF 的当前信息。该命令的输出如下所示:

?????????????????????????????????????????????????????? ?????????????????????????????????????????????
? 恢复单元 ID ? 文件 ID ? 文件大小 ?起始偏移量?FSeqNo ? 地位 ?平价?创建LSN?
?????????????????????????????????????????????????????? ?????????????????????????????????????????????
? 0 ? 2 ? 268369920 ? 8192?34 ? 2 ? 64 ? 0 ?
? 0 ? 2 ? 268369920 ? 268378112 ? 0 ? 0 ? 0 ? 0 ?
? 0 ? 2 ? 268369920 ? 536748032 ? 0 ? 0 ? 0 ? 0 ?
? 0 ? 2 ? 268369920 ? 805117952 ? 0 ? 0 ? 0 ? 0 ?
?????????????????????????????????????????????????????? ?????????????????????????????????????????????

Status列指示给定 VLF 的状态,其中2指示 VLF 具有活动日志记录,并且在备份/截断这些记录(或在镜像的情况下,写入镜像的日志文件)之前无法重新使用。缩小日志文件(通常不建议这样做,除非您有问题)不能将文件的大小减小到最后一个状态为2. 在我上面的示例中,缩小日志文件将允许我摆脱最后 3 个 VLF,但是,我无法缩小第一个 VLF,因为它是 status 2。如果第 4 个 VLF 的状态为2,则在日志备份(完全恢复)或截断(简单恢复)之前,我根本无法缩小日志文件。

您可以使用以下查询查看文件大小和增长设置:

SELECT [DB Name] = d.name
    , [File Name] = mf.name
    , mf.physical_name
    , Size = mf.size * 8192E0 / 1048576
    , MaxSize = mf.max_size * 8192E0 / 1048576
    , Growth = mf.growth * 8192E0 / 1048576
    , [Recovery Model] = CASE WHEN mf.type = 1 THEN d.recovery_model_desc ELSE '' END
    , [Log Reuse Wait Reason] = CASE WHEN mf.type = 1 THEN d.log_reuse_wait_desc ELSE '' END
FROM master.sys.databases d
    INNER JOIN master.sys.master_files mf ON d.database_id = mf.database_id
WHERE d.name = DB_NAME()
ORDER BY d.name
    , mf.type
    , mf.name;
Run Code Online (Sandbox Code Playgroud)

上述查询的示例输出如下所示:

?????????????????????????????????????????????????????? ???????????????????????????????????????????????????
? D B ?文件 ?物理名称?尺寸 ?最大尺寸?生长 ?恢复 ?日志重用 ?
? 姓名 ?姓名 ?? ? ? ? 模型 ?等等原因?
?????????????????????????????????????????????????????? ???????????????????????????????????????????????????
? 测试 ?我的档案?D:\Data\Test_MyFile.bak ? 125?1000 ? 100 ? ? ?
? 测试 ?测试数据库?D:\Data\Test_DB.mdf ?384?2048?128?? ?
? 测试 ?测试日志?D:\Logs\Test_DB.ldf ? 256?2048?128?简单的 ?没有 ?
?????????????????????????????????????????????????????? ???????????????????????????????????????????????????

您可以使用以下查询查看 SQL Server 2012+ 的日志空间使用情况:

SELECT su.database_id
    , LogSizeMB = su.total_log_size_in_bytes / 1048576E0
    , LogUsedMB = su.used_log_space_in_bytes / 1048576E0
    , LogUsedPercent = su.used_log_space_in_percent
FROM sys.dm_db_log_space_usage su;
Run Code Online (Sandbox Code Playgroud)

sys.dm_db_log_space_usage输出是这样的:

?????????????????????????????????????????????????????? ?????????
? 数据库 ID ? 日志大小MB ? LogUsedMB ? 日志已用百分比?
?????????????????????????????????????????????????????? ?????????
? 7 ? 255.9921875?6.171875?2.410962?
?????????????????????????????????????????????????????? ?????????

SQL Server 2016+ 包含一个名为 的动态管理函数sys.dm_db_log_info,它提供有关 VLF 的详细信息。

如何使用它的示例:

DECLARE @DatabaseId tinyint = DB_ID('msdb');
SELECT DatabaseName = d.name
    , FileName = mf.physical_name
    , ddli.vlf_begin_offset
    , ddli.vlf_size_mb
    , ddli.vlf_active
    , ddli.vlf_status
FROM sys.dm_db_log_info (@DatabaseId) ddli
    INNER JOIN sys.databases d ON ddli.database_id = d.database_id
    INNER JOIN sys.master_files mf ON ddli.file_id = mf.file_id AND ddli.database_id = mf.database_id
ORDER BY d.name
    , mf.file_guid;
Run Code Online (Sandbox Code Playgroud)

输出看起来像:

?????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ??????
? 数据库名称 ?文档名称 ?vlf_begin_offset ? vlf_size_mb ? vlf_active ? vlf_status ?
?????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ??????
? msdb ? F:\Data\msdb\log\msdblog.ldf ? 31064064 ? 10 ? 0 ? 0 ?
? msdb ? F:\Data\msdb\log\msdblog.ldf ? 41549824?10 ? 0 ? 0 ?
? msdb ? F:\Data\msdb\log\msdblog.ldf ? 52035584?10 ? 1 ? 2 ?
? msdb ? F:\Data\msdb\log\msdblog.ldf ? 62521344?10 ? 0 ? 0 ?
? msdb ? F:\Data\msdb\log\msdblog.ldf ? 73007104 ? 10 ? 0 ? 0 ?
? msdb ? F:\Data\msdb\log\msdblog.ldf ? 83492864?10 ? 0 ? 0 ?
? msdb ? F:\Data\msdb\log\msdblog.ldf ? 93978624 ? 10.37?0 ? 0 ?
?????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ??????

有关日志的汇总详细信息,sys.dm_db_log_stats提供了很好的信息:

SELECT *
FROM sys.dm_db_log_stats(@DatabaseId)
Run Code Online (Sandbox Code Playgroud)

输出包括以下列:

数据库 ID
恢复模型
log_min_lsn
log_end_lsn
current_vlf_sequence_number
current_vlf_size_mb
total_vlf_count
total_log_size_mb
active_vlf_count
active_log_size_mb
log_truncation_holdup_reason
日志备份时间
log_backup_lsn
log_since_last_log_backup_mb
log_checkpoint_lsn
log_since_last_checkpoint_mb
log_recovery_lsn
log_recovery_size_mb
recovery_vlf_count

有关更多详细信息,我在 SQLServerScience.com 上写了一篇关于为最佳 VLF 数量调整日志文件大小的博客文章。


Rob*_*gie 5

当然,是否使用完全恢复非常重要,因为这需要更大的日志文件。这意味着您的备份不是防止数据丢失的唯一保护措施。重要的是,丢失任何数据对业务都非常不利。我们中的一些人偶尔会丢失一天的数据。

一些相关阅读:

https://www.brentozar.com/blitz/high-virtual-log-file-vlf-count/

https://www.sqlskills.com/blogs/kimberly/transaction-log-vlfs-too-many-or-too-few/

https://www.sqlskills.com/blogs/paul/important-change-vlf-creation-algorithm-sql-server-2014/

第一个断言 1000 个虚拟日志文件是计划在方便时采取行动的理由,并链接到说明。好了,概述了一种方法。

第二个评论是 VLF 可能太少也可能太大。

第三个描述了在 SQL Server 2014 之前和之后,行为发生变化的给定增量大小内创建了多少 VLF 的公式。为什么不让我们说有多少...

你也可以考虑有多少物理日志文件......

在这里,我们有很多数据库,有些大,有些小,我们使用简单恢复。我认为实际上我为日志自动增长选择的折衷点是 1 MB (!) 初始大小和 63 MB 增量,构成 4 个虚拟日志文件,而 64 MB 增量会产生 8 个 VLF。对于较小的数据库,我增加了 16 MB,期望当 1 MB 不是时,这将足以满足轻度使用的总日志空间:并且无需为每个大小提供 64 MB 作为下一个大小步骤,正如我所说的那样,我有很多数据库。

(更新 - 添加了“因为这需要更大的日志文件”。)