10.4 截断事务日志
10.4.1 虚拟日志文件
SQL Server 把事务日志文件划分为多个虚拟日志文件(Virtual Log File,缩写为VLF)。
每个 VLF 处于以下状态之一:
◆ 活动(Active)
表示 VLF 中存在活动的事务,这些事务等待被提交或者被回滚。
◆ 可恢复(Recoverable)
表示 VLF 中的事务全部已经完成,但是某些操作(例如数据库镜像、复制等)还需要用到这些数据,因此不可以被覆盖。
◆ 可复用(Reusable)
表示 VLF 中的数据已经被截断了,可以被覆盖。
◆ 未用(Unused)
表示 VLF 未被使用。
可以执行 DBCC LogInfo,检查 VLF 的使用情况。下表是一个示例结果。
上表中的 FileID 为 2,表示事务日志文件是这个数据库的第 2 个文件。FileSize 表示 VLF 的大小。FSeqNo 表示 VLF 的序列号,如果为零则表示这个VLF未被使用。CreateLSN 为零,表示创建数据库时就同时创建了这些VLF;不为零则表示在 LSN 产生时才创建这个 VLF。Status 列表示 VLF 的状态,如果为 0 则表示这个 VLF 为 Reusable 或者 Unused;如果为 2 则表示这个 VLF 为 Active 或者 Recoverable。
使用系统函数 fn_dblog 可以查看事务日志。例如,下例的语句可以查看所有的日志。
SELECT * FROM::fn_dblog(null,null) |
以下是一个示例结果。
上图第1列显示的16进制 Current LSN 不能直接使用,需要换算成正常的10进制 LSN。以第一行为例,第1段为VLF序列号,00B1 换算成10进制为177;第2段为日志区块的第1个扇区编号,6FB8换算成10进制为0000028600(10位数);第3段为该扇区内的流水号,换算成10进制为00001(5位数)。因此,正常的LSN为177000002860000001。
根据 FSeqNo 可以查看该 VLF 中包含的事务日志。例如,查看 FSeqNo= 182,可以使用以下语句。
SELECT * FROM::fn_dblog(182000000000000001,183000000000000000) |
10.4.2 截断事务日志
事务日志文件内部使用回绕的机制,事务日志按顺序写入 VLF,当写满最后一个VLF(物理日志文件的尾端)后再回绕到第一个可用的 VLF 继续写入。
当全部 VLF 的 Status 都变成 2 时,SQL Server 需要向操作系统申请更多的磁盘空间给事务日志文件(如果启用了自动增长);如果禁用了自动增长,或者事务日志文件已经达到了上限值,那么数据库引擎将会报告“数据库事务日志已满”的错误(错误代码为9002)。
事务日志可以被截断,从而将 VLF 的 Status 从 2 修改为 0,从而腾出可用的空间。如果经常截断旧的日志记录,始终为新日志记录保留足够的空间,则物理日志文件永远不会填满。日志截断可从 SQL Server 数据库的逻辑事务日志中删除不活动的虚拟日志文件,释放逻辑日志中的空间以便物理事务日志重用这些空间。如果事务日志从不截断,它最终将填满分配给物理日志文件的所有磁盘空间。
在截断事务日志之前,SQL Server 必须找到一个 MinLSN(即最小的日志序列号),这个MinLSN之前的所有事务日志记录都将释放,并且将位于 MinLSN 之前的 VLF 标记为可复用。
日志文件中从 MinLSN 到最后写入的日志记录这一部分称为日志的活动部分,或者称为“活动日志”。 这是进行数据库完整恢复所需的日志部分。永远不能截断活动日志的任何部分。所有的日志记录都必须从 MinLSN 之前的日志部分截断。
下图显示了具有两个活动事务的事务日志的简化版本。
LSN 147 是事务日志中的最后一条记录。在处理 LSN 146 截断日志时,Tran 1 已经提交,而 Tran 2 是唯一的活动事务。这就使 Tran 2 的第一条日志记录成为截断日志时处于活动状态的事务的最旧日志记录。 这使 LSN 142(Tran 2 的开始事务记录)成为新的 MinLSN。
10.4.3 可能延迟日志截断的因素
在日志记录长时间处于活动状态时,事务日志截断将延迟,事务日志可能填满。
日志截断会由于多种因素发生延迟。可以查询 sys.databases 目录视图的 log_reuse_wait 和 log_reuse_wait_desc 列来发现是哪些因素(如果有)阻止截断日志。下表对这些列的值进行了说明。
log_reuse_wait 值 | log_reuse_wait_desc 值 |
说明 |
0 | NOTHING |
当前有一个或多个可重复使用的虚拟日志文件。 |
1 |
CHECKPOINT |
自上次日志截断之后,尚未生成检查点,或者日志头尚未跨一个虚拟日志文件移动。这是日志截断延迟的常见原因。 |
2 |
LOG_BACKUP |
在截断事务日志前,需要进行日志备份。(仅限完整恢复模式或大容量日志恢复模式) 完成下一个日志备份后,一些日志空间可能变为可重复使用。 |
3 |
ACTIVE_BACKUP_OR_RESTORE |
数据备份或还原正在进行。如果数据备份阻止了日志截断,则取消备份操作可能有助于解决备份直接导致的此问题。 |
4 |
ACTIVE_TRANSACTION |
事务处于活动状态。 |
5 |
DATABASE_MIRRORING |
数据库镜像暂停,或者在高性能模式下,镜像数据库明显滞后于主体数据库。 |
6 |
REPLICATION |
在事务复制过程中,与发布相关的事务仍未传递到分发数据库。 |
7 |
DATABASE_SNAPSHOT_CREATION |
正在创建数据库快照。 |
8 |
LOG_SCAN |
发生日志扫描。 |
9 |
AVAILABILITY_REPLICA |
可用性组的辅助副本正将此数据库的事务日志记录应用到相应的辅助数据库。 |
13 |
OLDEST_PAGE |
如果将数据库配置为使用间接检查点,数据库中最早的页可能比检查点 LSN 早。在这种情况下,最早的页可以延迟日志截断。 |
10.4.4 收缩事务日志文件
收缩日志文件可删除一个或多个不包含逻辑日志任何部分的虚拟日志文件(即“不活动的虚拟日志文件”)。在收缩事务日志文件时,将从日志文件的末端删除足够的不活动虚拟日志文件,以便将日志减小到接近目标大小。
截断日志之后,事务日志并不会自动收缩。打开 SSMS,右键单击要收缩的数据库。依次指向“任务”和“收缩”,再单击“文件”。
在收缩文件对话窗口,选择文件类型为“日志”。如果有多个日志文件,则可以在文件名下拉框中选择对应日志文件的逻辑名称。
T-SQL 语句示例如下:
DBCC SHRINKFILE (N'SQLDB01_log' , 0, TRUNCATEONLY) |
本文出自 “SQL Server 管理员指南” 博客,谢绝转载!