多次收缩 SQL Server 日志文件

Cra*_*ein 5 sql-server-2008 transaction-log

最近遇到一个情况,在进行日志备份和收缩文件后,LDF 文件大小保持不变。DBCC LOGINFO 清楚地显示只有一个活动的 VLF 和 SSMS 表示 LDF 中 99% 的空间是空闲的。第一次尝试没有缩小,第二次尝试或第三次尝试也没有缩小。第四次尝试成功后,日志减少到请求的大小。同时,DBCC LOGINFO 说在每个 SHRINKFILE 之后,另一个 VLF 变得活跃。

我决定运行一个新数据库的测试。

CREATE DATABASE logs_test
USE logs_test

-- first look at the VLFs for the logs_test database
DBCC LOGINFO

/*
FileId      FileSize             StartOffset          FSeqNo      Status      Parity CreateLSN
----------- -------------------- -------------------- ----------- ----------- ------ ---------------------------------------
2           253952               8192                 19          2           64     0
2           253952               262144               0           0           0      0

*/

-- put the database into FULL recovery before making a backup
ALTER DATABASE logs_test SET RECOVERY FULL

-- first look at the VLFs for the logs_test database
DBCC LOGINFO


/*
FileId      FileSize             StartOffset          FSeqNo      Status      Parity CreateLSN
----------- -------------------- -------------------- ----------- ----------- ------ ---------------------------------------
2           253952               8192                 19          2           64     0
2           253952               262144               0           0           0      0

*/

BACKUP DATABASE logs_test TO DISK = 'D:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Backup\logs_test_250503.bak'
WITH INIT
GO

DBCC LOGINFO

/*
FileId      FileSize             StartOffset          FSeqNo      Status      Parity CreateLSN
----------- -------------------- -------------------- ----------- ----------- ------ ---------------------------------------
2           253952               8192                 60          2           128    0
2           253952               262144               24          0           64     0
*/

-- create a table to put stuff in
CREATE TABLE newtable(a int);
GO

INSERT INTO newtable VALUES(10);
INSERT INTO newtable VALUES(20);
INSERT INTO newtable VALUES(30);
GO

-- run the update script again, the log file has grown to accomodate the log records
SET NOCOUNT ON
DECLARE @counter int
SET @counter = 1;
WHILE @counter < 100000 BEGIN
    UPDATE newtable SET a = a + 1
    SET @counter = @counter + 1;
END;

DBCC LOGINFO

/*
FileId      FileSize             StartOffset          FSeqNo      Status      Parity CreateLSN
----------- -------------------- -------------------- ----------- ----------- ------ ---------------------------------------
2           253952               8192                 23          2           64     0
2           253952               262144               24          2           64     0
2           270336               516096               25          2           64     24000000013400005
2           262144               786432               26          2           64     25000000016700003
2           262144               1048576              27          2           64     26000000015000005
2           262144               1310720              28          2           64     27000000015000005
*/
Run Code Online (Sandbox Code Playgroud)

到目前为止一切顺利,添加了 VLF 并且它们的状态为 2。我运行了一个备份日志

BACKUP LOG logs_test TO DISK = 'D:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Backup\logs_test_250503.trn'
WITH INIT
GO
Run Code Online (Sandbox Code Playgroud)

然后我运行 DBCC LOGINFO ,有一个活动的 VLF,正是我所期待的

DBCC LOGINFO
/*
FileId      FileSize             StartOffset          FSeqNo      Status      Parity CreateLSN
----------- -------------------- -------------------- ----------- ----------- ------ ---------------------------------------
2           2162688              92930048             145         0           64     141000000347800005
2           2359296              95092736             146         0           64     145000000386300003
2           2359296              97452032             147         0           64     145000000386300003
2           2359296              99811328             148         0           64     145000000386300003
2           2424832              102170624            149         2           64     145000000386300003
*/
Run Code Online (Sandbox Code Playgroud)

所以现在我运行我的shrinkfile命令,认为我将剩下1MB的LDF

DBCC SHRINKFILE (N'logs_test_log' , 1)
DBCC LOGINFO

/*
FileId      FileSize             StartOffset          FSeqNo      Status      Parity CreateLSN
----------- -------------------- -------------------- ----------- ----------- ------ ---------------------------------------
2           253952               8192                 109         2           128    0
2           253952               262144               97          0           64     0
2           270336               516096               98          0           128    61000000013500003
2           262144               786432               99          0           128    62000000016600005
2           262144               1048576              100         0           128    63000000015100003
2           262144               1310720              101         0           128    64000000015000005
2           262144               1572864              102         0           128    65000000015100003
2           262144               1835008              103         0           128    66000000015000005
2           262144               2097152              104         0           128    67000000015100003
2           262144               2359296              105         0           128    68000000015000005
2           262144               2621440              106         0           128    69000000015100003
2           327680               2883584              107         0           128    70000000015100003
2           327680               3211264              108         2           128    71000000027800005
*/
Run Code Online (Sandbox Code Playgroud)

运气不好,LDF 仍然是 100MB,现在有两个活动的 VLF

所以我再次运行shrinkfile,因为可用空间量没有改变99%

DBCC SHRINKFILE (N'logs_test_log' , 1)
DBCC LOGINFO


/*
FileId      FileSize             StartOffset          FSeqNo      Status      Parity CreateLSN
----------- -------------------- -------------------- ----------- ----------- ------ ---------------------------------------
2           253952               8192                 109         2           128    0
2           253952               262144               110         2           128    0
2           270336               516096               111         2           64     61000000013500003
2           262144               786432               99          0           128    62000000016600005
2           262144               1048576              100         0           128    63000000015100003
2           262144               1310720              101         0           128    64000000015000005
2           262144               1572864              102         0           128    65000000015100003
2           262144               1835008              103         0           128    66000000015000005
2           262144               2097152              104         0           128    67000000015100003
2           262144               2359296              105         0           128    68000000015000005
2           262144               2621440              106         0           128    69000000015100003
2           327680               2883584              107         0           128    70000000015100003
2           327680               3211264              108         2           128    71000000027800005
*/
Run Code Online (Sandbox Code Playgroud)

仍然没有运气,LDF 仍然是 100MB,现在有四个活动的 vlfs

所以我最后一次运行了shrinkfile,这就是我得到的

DBCC SHRINKFILE (N'logs_test_log' , 1)
DBCC LOGINFO

FileId      FileSize             StartOffset          FSeqNo      Status      Parity CreateLSN
----------- -------------------- -------------------- ----------- ----------- ------ ---------------------------------------
2           253952               8192                 150         2           128    0
2           253952               262144               151         2           128    0
2           270336               516096               152         2           128    20000000013400005
2           262144               786432               153         2           128    21000000016600005
2           262144               1048576              154         2           128    22000000015000005
2           262144               1310720              155         2           128    23000000015100003
2           262144               1572864              25          0           64     24000000015000005
Run Code Online (Sandbox Code Playgroud)

6 个活动的 VLF 和一个 1MB 的 LDF 文件

我的问题是这样的。

  1. 为什么需要多次运行 SHRINKFILE 来缩小 LDF?
  2. 使用 1MB 的 LDF,为什么我仍然在 DBCC LOGINFO 中显示这么多 VLF?
  3. 是否有可能知道每个 VLF 中存储了什么?我有 LSN,但想知道发生了什么操作。

谢谢

更新 15:41

这是我在阅读日志内容中找到的内容

谢谢大家的意见。

Aar*_*and 4

下次,在尝试收缩文件(假设简单恢复)或进行两次日志备份(假设完整或批量记录)之前运行两个检查点。这将强制日志回绕到文件的开头,从而允许收缩文件操作根除文件的大部分内容。我认为第四次操作成功只是巧合(也许同时发生了多个检查点)。

\n\n

也就是说,您到底为什么需要 1 MB 的日志文件?如果它生长过一次,​​它就会再次生长。暂时释放空间,以便它可以在实际活动期间自动增长(这会阻塞,因为即使使用即时文件初始化,日志的增长也必须为零初始化)似乎是徒劳的。为什么不适当地调整日志的大小,这样您就不必处理增长(理想情况下)或收缩(浪费)。

\n\n

请仔细阅读这个问题及其答案:

\n\n

为什么事务日志不断增长或空间不足?

\n\n

进一步阅读可能比尝试总结更有用:

\n\n\n