曲苑杂坛--收缩数据库日志

时间:2022-03-16 07:16:51

--===============================================

这是个老生常谈的问题,很多新人都会被较大的日志文件所困扰,对此,我抛砖引玉,献丑总结下。

--===============================================

收缩数据库日志文件和收缩数据库数据文件一样,都是从文件尾部收缩,因此如果需要收缩日志文件,就必要先将日志文件尾部区域未被使用,而日志按照虚拟日志文件的方式存放,通过虚拟日志文件的status来查看其状态,通过虚拟日志文件的startoffset来查看其位置。

--=======================================================
--使用DBCC LOGINFO 来查看虚拟日志文件
--DBCC LOGINFO 属于undocumented,在MSDN查找不到相关解释
--VLF状态解释请参考:http://www.cnblogs.com/TeyGao/p/3522937.html
--1.活动(ACTIVE),在VLF上有任一条LSN是活动的
--2.可恢复(RECOVERABLE),VLF上的LSN不活动的,但尚未被截断(truncated),该片区域的日志将可能被用于备份/镜像/复制等
--3.可重用(REUSED),VLF上无活动的LSN,且已经被截断,该空间可以被再次使用
--4.未使用(UNUSED),VLF是不活动的,且空间从未被使用过

--Status=0表示可重用或未使用
--Status=2表示活动或可恢复
DBCC LOGINFO

曲苑杂坛--收缩数据库日志

 只有尾部的虚拟日志文件VLF处于可重用(REUSED)和未使用(UNUSED),收缩日志文件方有效果。

 

对于日志文件无法收缩的情况,我们按以下顺序分析原因

1. 查看是否有长时间未提交的事务

--===================================================================
--DBCC OPENTRAN
--如果在指定数据库内存在最早的活动事务和最早的分布式和非分布式复制事务,
--则显示与之有关的信息。仅当存在活动事务或数据库包含复制信息时,才显示
--结果。如果没有活动事务,就显示信息性消息。
--参考:http://msdn.microsoft.com/zh-cn/library/ms182792(v=sql.90).aspx

DBCC OPENTRAN

长时间未提交的事务会导致自该事务开始的后续事务都无法截断,因此也无法收缩。

2. 查看日志等待重用的原因

--======================================================
--查看日志等待重用的原因
--参考:http://msdn.microsoft.com/zh-cn/library/ms178534.aspx
SELECT DB.name,
DB.log_reuse_wait_desc
FROM sys.databases DB 

通常情况下,日志会等待镜像和复制的重用,我们可以根据情况修复镜像和复制,而如果日志等待备份,则先做日志备份再尝试收缩。

PS:有部分DBA只进行一次日志备份,发现无法收缩数据库,便认为日志备份方式无效,如果耐心多执行几次备份收缩(先日志备份再立即收缩日志文件),便会发现日志可以被成功缩小,这是因为在日志备份后,日志文件尾部还存在活动的虚拟日志文件。

 

3. 检查是否由于初始日志文件过大无法收缩

在创建数据库时生成的VLF,无论其存于何种状态,都无法收缩。对于此种情况,只能使用分离附加的方式来为数据库重新生成新的日志文件。

 

 --======================================================

对于由CDC引起的日志文件无法收缩问题,如果CDC可以重做的情况下,可以运行以下命令来处理:

--===========================
--如果CDC已关闭,先暂时启用
EXEC sp_cdc_enable_db
GO
--=========================
--使用sp_repldone来将复制日志标记为无用
EXEC sp_repldone 
@xactid = NULL, 
@xact_segno = NULL, 
@numtrans = 0, 
@time = 0,
@reset = 1
GO
--=======================
--关闭CDC
EXEC sys.sp_cdc_disable_db