每个 SQL Server 数据库都具有事务日志,用于记录所有事务以及每个事务对数据库所做的修改。事物日志的作用主要如下:
对于内存中的脏页的刷盘主要有以下两种方式:
如上图,SQL Server的日志由多个虚拟日志文件(Vitual Log Files(VLF))组成,事务日志被截断的基本单位是VLF而不是数据页,对于事务日志中的日志记录都有自己的逻辑序列号(LSN)进行标记。
1、事物日志状态分类
2、事务日志截断
事物日志截断是以VLF为单位来做截断的,日志截断可以释放日志文件的空间,以便由事务日志重新使用。若事物日志长时间不截断会导致事物日志的不断增长,直至磁盘空间打满。在生产环境中,我们必须做好事物日志的监控,周期性对事物日志进行截断。
3、事物日志自动截断的场景:
事物日志的截断并不会减少事物日志物理文件的大小,而是清理出一些可重用空间以供新的事物日志写入进行复用。若想要对事物日志的物理文件大小进行收缩,需要进行专门的日志收缩操作。
1、查看当前数据库事物日志文件大小以及日志使用率等
SELECT a.name [文件名称] ,cast(a.[size]*1.0/128 as decimal(12,1)) AS [文件大小(MB)] ,
CAST( fileproperty(s.name,'SpaceUsed')/(8*16.0) AS DECIMAL(12,1)) AS [日志使用空间(MB)] ,
CAST( (fileproperty(s.name,'SpaceUsed')/(8*16.0))/(s.size/(8*16.0))*100.0 AS DECIMAL(12,1)) AS [日志空间使用率%] ,
CASE WHEN A.growth =0 THEN '文件大小固定,不会增长' ELSE '文件将自动增长' end [增长模式] ,CASE WHEN A.growth > 0 AND is_percent_growth = 0
THEN '增量为固定大小' WHEN A.growth > 0 AND is_percent_growth = 1 THEN '增量将用整数百分比表示' ELSE '文件大小固定,不会增长' END AS [增量模式] ,
CASE WHEN A.growth > 0 AND is_percent_growth = 0 THEN cast(cast(a.growth*1.0/128as decimal(12,0)) AS VARCHAR)+'MB'
WHEN A.growth > 0 AND is_percent_growth = 1 THEN cast(cast(a.growth AS decimal(12,0)) AS VARCHAR)+'%' ELSE '文件大小固定,不会增长' end AS [增长值(%或MB)] ,
a.physical_name AS [文件所在目录] ,a.type_desc AS [文件类型]
FROM sys.database_files a
INNER JOIN sys.sysfiles AS s ON a.[file_id]=s.fileid
LEFT JOIN sys.dm_db_file_space_usage b ON a.[file_id]=b.[file_id] ORDER BY a.[type]
2)监控事物日志状态
select name,log_reuse_wait,log_reuse_wait_desc from sys.databases;
log_reuse_wait | log_reuse_wait_desc | 说明 |
---|---|---|
0 | NOTHING | 当前有一个或多个可重复使用的虚拟日志文件 (VLF)。 |
1 | CHECKPOINT | 自上次日志截断之后,尚未生成检查点,或者日志头尚未跨一个虚拟日志 (VLF) 文件移动。 (所有恢复模式)这是日志截断延迟的常见原因。 |
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 | 可用性组的辅助副本正将此数据库的事务日志记录应用到相应的辅助数据库。 (完整恢复模式) |
10 | - | 仅供内部使用 |
11 | - | 仅供内部使用 |
12 | - | 仅供内部使用 |
13 | OLDEST_PAGE | 如果将数据库配置为使用间接检查点,数据库中最早的页可能比检查点日志序列号 (LSN) 早。 在这种情况下,最早的页可以延迟日志截断。 (所有恢复模式) |
14 | OTHER_TRANSIENT | 当前未使用此值。 |
16 | XTP_CHECKPOINT | 需要执行内存中 OLTP 检查点。对于内存优化表,如果上次检查点后事务日志文件变得大于 1.5 GB(包括基于磁盘的表和内存优化表),则执行自动检查点 |
1、事物日志打满解决策略
生产环境中我们一般建议使用“FULL”恢复模式,但是在FULL恢复模式下需要我们周期性的对数据库以及事物日志进行备份,避免事物日志因无法被截断而导致事物日志文件不断增大。当事物日志文件打满的情况,我们可以有如下解决策略:
2、如何进行事物日志文件收缩?
在FULL/大容量日志恢复模式下,只有对事物日志进行备份后,才可对事物日志文件进行截断,截断后才可手动对事物日志文件进行一定的收缩处理;对于simple的恢复模式,数据库引擎会在每次checkpoint或者日志备份后自动对事物日志进行截断,一般情况下事物日志文件不会太大。另外对于日志收缩,事物日志文件不能小于一个VFL大小。
1)直接对事物日志文件进行收缩
USE AdventureWorks2012;
GO
DBCC SHRINKFILE (AdventureWorks2012_Log, 1);
GO
2)将数据库恢复模式设置为 SIMPLE 来截断该文件
USE AdventureWorks2012;
GO
-- Truncate the log by changing the database recovery model to SIMPLE.
ALTER DATABASE AdventureWorks2012
SET RECOVERY SIMPLE;
GO
-- Shrink the truncated log file to 1 MB.
DBCC SHRINKFILE (AdventureWorks2012_Log, 1);
GO
-- Reset the database recovery model.
ALTER DATABASE AdventureWorks2012
SET RECOVERY FULL;
GO