在这篇文章里,我想详细谈下为什么你要避免事务日志(Transaction Log)上的自动增长操作(Auto Growth operations)。很多运行的数据库服务器,对于事务日志,用的都是默认的日志文件大小和自动增长设置。人们有时会很依赖自动增长机制,因为它们刚好能正常工作。当然,如果它正常工作的话,你不必太关注它,但很快你会发现会有问题出现。

只依赖于事务日志的自动增长机制总不是个好主意。首先它会导致严重的日志碎片(Log Fragmentation),在SQL Server启动期间,在你数据库上执行崩溃恢复(Crash Recovery)时会有很大的负面影响。另外,在你数据库里写入事务需要等待,只要事务日志触发了自动增长机制。

当事务日志的自动增长机制发生时,SQL Server总要零初始化新块,这个会在文件末尾加上。这和你的SQL Server实例是否用即时文件初始化(Instant File Initialization)特权——事务日志总会零初始化。这上面的原因非常明显:当SQL Server在过去已经完成事务日志的环绕式处理(wrap-around ),崩溃恢复(Crash Recovery)需要知道在哪里停。

零初始化的问题是会占用更多的时间(取决与你的自动增长率,还有你的存储速度)。在此期间没有别的事务可以写事务日志记录到事务日志。在事务日志管理器上会有闩锁造成的阻塞。因此你的写入事务会进入挂起状态(直到它们获得需要的闩锁),它们就等啊,等啊,等啊,直到你的事务日志自动增长完成。让我们用一个简单的例子演示下。

首先我为这个演示创建一个新的数据库。对于这个数据库,这里我不用默认的设置,对于事务日志,我指定了10GB的自动增长系数。这个的确是个不好的做法,但我只是用它来展示这个设置的副作用。请不要在你的生产数据库里使用这个错误配置!!!

 1 -- Create a new database with 10 GB Auto Growth for the Transaction Log
 2 CREATE DATABASE AutoGrowthTransactionLog ON PRIMARY
 3 (
 4     NAME = N'AutoGrowthTransactionLog',
 5     FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\AutoGrowthTransactionLog.mdf',
 6     SIZE = 5120KB,
 7     FILEGROWTH = 1024KB
 8 )
 9 LOG ON
10 (
11     NAME = N'AutoGrowthTransactionLog_log',
12     FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\AutoGrowthTransactionLog_log.ldf',
13     SIZE = 1024KB,
14     FILEGROWTH = 10240000KB -- 10 GB Auto Growth!
15 )
16 GO

下一步里我在数据库里创建2个表。第1个表我通过插入一些日志来快速填充我的事务日志。在事务日志自动增长阶段,我们在第2个表里插入新的记录来证明这个事务会被自动增长机制阻塞。

 1 -- Create a new table, every records needs a page of 8kb
 2 CREATE TABLE Chunk
 3 (
 4     Col1 INT IDENTITY PRIMARY KEY,
 5     Col2 CHAR(8000)
 6 )
 7 GO
 8
 9 -- Another simple table
10 CREATE TABLE Foo
11 (
12     Bar INT NOT NULL
13 )
14 GO

现在我们已经创建了必须的数据库对象,因次我可以通过新的没有立即提交的事务来填充事务日志:

1 -- Begin a new transaction, that blocks the 1st VLF in the Transaction Log
2 BEGIN TRANSACTION
3 INSERT INTO Chunk VALUES (REPLICATE('x', 8000))
4 GO

因为我们现在有了进行中,没提交的事务,SQL Server不能重用那部分事务日志,即这个事务存储的事务日志。它们有需要回滚的可能。因此现在我通过不同的会话插入66条其他记录来填充事务日志:

1 INSERT INTO AutoGrowthTransactionLog.dbo.Chunk VALUES (REPLICATE('x', 8000))
2 GO 66

最后在第一个会话里提交我们的事务:

1 COMMIT

这意味着在我们面前有一个几乎满的的事务日志,我们可以通过DBCC LOGINFO来验证:

1 DBCC LOGINFO

现在当我们往表里插入兮的记录时,事务日志已经没有可用空间了,SQL Server进入事务日志的自动增长。

1 -- This statement will trigger the Auto Growth mechanism!
2 INSERT INTO Chunk VALUES (REPLICATE('x', 8000))
3 GO

在自动增长期间的同时,为了监控发生了什么,我们可以在SSMS里打开新的一个会话窗口,尝试在第2个表插入另外的记录——表Foo

1 -- This statement is now blocked by the Auto Growth mechanism.
2 INSERT INTO Foo VALUES (1)
3 GO

这个SQL 语句会阻塞,因为事务要写入事务日志记录的事务日志,当前不可用。为了进一步分析这个阻塞情形,你可以打开第3个会话窗口,执行下列2个SQL语句:

1 -- Analyze the blocking situation
2 SELECT wait_type, * FROM sys.dm_exec_requests
3 WHERE session_id IN (54, 55)
4
5 SELECT wait_type, * FROM sys.dm_os_waiting_tasks
6 WHERE session_id IN (54, 55)
7 GO

(额,俺本机测试失败………………)

从代码里可以看到,我用2个DMV sys.dm_exec_requests 和 sys.dm_os_waiting_tasks对2个会话都进行了跟踪——触发自动增长的会话,和被自动增长机制阻塞的会话。在这里,触发自动增长的会话里有所谓的抢占等待类型(Preemptive Wait Type)——PREEMPTIVE_OS_WRITEFILEGATHER。抢占等待类型是由SQL Server返回的等待类型,当SQL Server 执行一个WIN32 API函数在调度机制之外时。这里自动增长是通过WriteFileGather的WIN32 API函数完成的。

INSERT语句尝试在Foo表里插入新的记录出现LATCH_EX等待类型。如你从DMV sys.dm_os_waiting_tasks 里的resource_description列所见,在SQL Server的日志管理器上需要获得闩锁。你可以通过查询DMV sys.dm_os_latch_stats 限制lactch class为LOG_MANAGER再次确认。在那个特定闩锁上你会看到一些等待。那个闩锁是事务获取的,由事务日志的自动增长触发,只要这个闩锁要获得,每个其他写事务都会被阻塞。因此在系统上有大量等待时间时,这暗示这在事务日志里当前有自动增长问题需要处理。

希望我已经用这个日志说服你,依赖于事务日志的自动增长机制并不是最好的解决方案。用这个简单的例子可以看到,在你数据库里每个被自动增长操作阻塞的写入事务会发生阻塞,这肯定会伤及你数据库的吞吐量和扩展性。为了保证你有很好的事务日志性能,你可以最佳想实践下这个文章。

感谢关注!

参考文章:

https://www.sqlpassion.at/archive/2014/01/07/why-transaction-log-auto-growths-are-degrading-your-performance/

转载于:https://www.cnblogs.com/woodytu/p/4626396.html

为什么事务日志自动增长会降低你的性能相关推荐

  1. SQL Server 为什么事务日志自动增长会降低你的性能

    原文地址:点击打开链接 在这篇文章里,我想详细谈下为什么你要避免事务日志(Transaction Log)上的自动增长操作(Auto Growth operations).很多运行的数据库服务器,对于 ...

  2. SQL Server中事务日志自动增长对性能的影响

    SQL Server中事务日志自动增长对性能的影响 SQL Server中事务日志自动增长对性能的影响(上) SQL Server中事务日志自动增长对性能的影响(下) posted on 2011-0 ...

  3. sqlserver 事务日志 异常增长原因排查_小白入门学习打日志

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 记得之前写过一篇:<阿里巴巴 Java开发手册 ...

  4. 清空数据库事务日志_通过事务日志增长加快数据库恢复和长期运行的事务

    清空数据库事务日志 In my previous article in this series Accelerated Database Recovery; Instant Rollback and ...

  5. SQL Server事务日志–第2部分–日志性能问题的主要原因

    In the previous article, we have examined the physical structure of the transaction log and discusse ...

  6. [ZT]SQL Server 的事务日志意外增大或充满的处理方法

    http://support.microsoft.com/kb/317375 事务日志文件Transaction Log File是用来记录数据库更新情况的文件,扩展名为ldf. 在 SQL Serv ...

  7. SQL Server 事务日志的问题

    关于SQL SERVER 日志满的处理方法 事务日志文件Transaction Log File是用来记录数据库更新情况的文件,扩展名为ldf. 在 SQL Server 7.0 和 SQL Serv ...

  8. 有关SQL Server事务日志的十大文章

    了解SQL Server中的日志记录和恢复 (Understanding Logging and Recovery in SQL Server) "Understanding Logging ...

  9. 什么是SQL Server事务日志中的虚拟日志文件?

    什么是SQL Server事务日志文件? (What is a SQL Server transaction log file?) SQL Server事务日志文件是每个SQL Server数据库的组 ...

最新文章

  1. 新冠影响男性生育能力,肾脏睾丸易感染,科学家建议康复患者检查生殖系统...
  2. linux得到当前系统时间,在LINUX下用C++编程,怎么获取系统当前的时间。
  3. C# Web实时消息后台服务器推送技术-GoEasy
  4. win8学习--------计时器
  5. python3 之 天天生鲜 项目 缓存cache
  6. 微课|玩转Python轻松过二级(2.1节):常用内置对象
  7. VB.NET和C#的比较
  8. 用iFrame遮挡DropDownList的方法
  9. paip.python错误解决5
  10. 单片机仿真软件Proteus8.0的安装及使用
  11. 【宋红康 MySQL数据库 】【高级篇】【10】索引的创建与删除_MySQL8.0的索引新特性
  12. Camtasia Studio 8
  13. 使用DirectSound播放MP3文件
  14. MOGRT视频制作库 Premiere遮罩/转场/特效视频剪辑效果模板库预设
  15. sql/oracle数据库之取整函数round()、ceil()、floor()等等及示例
  16. C++常用头文件汇总
  17. r语言中如何进行两组独立样本秩和检验
  18. 乘车码来了,地铁公交都可以刷微信了
  19. 操作系统64位和32位的区别。
  20. [动态规划]最长公共子序列

热门文章

  1. python标准库os.path中_Python零基础入门学习19:常用标准库之os.path子库
  2. 14英寸电脑长宽多少_华为MateBook 14 2020款 14英寸轻薄笔记本王者升级
  3. c语言上机填空改错试题,2013年计算机二级C语言上机试题六十二及答案
  4. tranmac不能识别_U盘插入苹果mac系统不能识别的解决方法
  5. python3 float最大值_Python3(3) Python 函数
  6. Python之代码性能分析工具(时间+内存)
  7. 深度残差网络_深度残差收缩网络:(三) 网络结构
  8. 130712周赛(CF)
  9. 如何测试W5300的内部TX/RX存储器?
  10. VS2012下基于Glut OpenGL glDepthMask示例程序: