Wednesday, September 22, 2010

如何使用SQLDiag工具来追踪死锁错误(ZT)

SQLDiag最初是在SQL Server 7.0中引入的,它是一个非常方便的工具可以用来监控数据库服务器中出现的问题。这个命令行工具可以为微软的客户提供必需的信息,在运行 时,SQLDiag可以将不同的SQL Server工具提供的数据输出到一个文本文件中,以便于您阅览,该文本文件包含了配置、数据库和错误日志的信息。
在SQL Server 2005中,您可以将 SQLDiag作为一个服务运行,也可以将它作为一个命令行工具。在以下的讨论中,我将假定您的机器上运行的是非集群的SQL Server 2000,而我将通过命令行提示符来发出命令。[b] [/b]
[b]实战[/b][b]SQLDiag[/b]
我觉得实际操作比阅读更容易吸收技术信息,让我们通过一个实例来看看SQLDiag是如何工作的,以及怎样用它让数据库管理员的日子好过些。在这个例子中,我将展示如何捕获造成数据库服务器死锁的语句,并进行研究,然后使用一些技巧性的调整来避免死锁的出现。
如果您对死锁不太熟悉,也不了解它们是怎样对数据库系统造成严重破坏的,可以参考我以前的文章,我可以对死锁做一些简单的解释,以及如何在SQL Server 2005中捕获死锁并重试。
在 服务器上捕获死锁信息之前,我必需开启服务器上的一些追踪标记,一个追踪标记是设定在SQL Server 中的一种状态,它可以监测到服务器对非法操作的响应。在这种情况下,我要开启可以监测死锁错误的追踪标记,并在错误发生时将这些信息写入错误日志。为了开 启这些追踪标记,请执行以下的命令:(您必需具备SQL Server系统管理员权限来运行DBCC命令)
DBCC TRACEON(1204, -1)
DBCC TRACEON(1205, -1)
DBCC TRACEON(3605, -1)
1204 标记将返回死锁时遇到的锁的类型;1205标记则会返回更加详细的信息,它可以记录出现死锁时正在运行的语句;3605标记将把追踪信息发送到错误日 志,SQLDiag工具可以将这些信息输出到一个文本文件中。命令中的“-1”参数表示对所有的数据库连接应用追踪标记。
现在系统已经具备捕获死锁的能力了,现在让我们来创造一个死锁的情况,在列表A中,我创建了一些表格来制造死锁。
IF EXISTS(SELECT [name] FROM sysobjects WHERE type = 'U' AND name = 'DeadlockTable1')
      DROP TABLE DeadlockTable1
GO
IF EXISTS(SELECT [name] FROM sysobjects WHERE type = 'U' AND name = 'DeadlockTable2')
      DROP TABLE DeadlockTable2
GO
CREATE TABLE DeadlockTable1
(
      IDCol TINYINT IDENTITY (1,1) PRIMARY KEY,
      DeadlockValue1 VARCHAR(20)
)
GO
CREATE TABLE DeadlockTable2
(
      IDCol TINYINT IDENTITY (1,1) PRIMARY KEY,
      DeadlockValue2 VARCHAR(20)
)
GO
列表A
现在表格已经创建好了,我将在每个表格中插入一行,这样我们就有一个值来更新了,我将使用两条临近的更新语句来造成死锁,如列表B所示:
INSERT INTO DeadlockTable1 (DeadlockValue1)
SELECT 'Deadlock1'
INSERT INTO DeadlockTable2 (DeadlockValue2)
SELECT 'Deadlock2'
GO
列表B
这 部分很有意思,在以上的代码中,我在每一个表格中都添加了一行更新语句,但是这两条语句又都在互相争夺表资源,最终会造成死锁情况的发生。在此,我将使用 两个单独的数据库连接,剪切并粘贴这部分SQL Server代码到一个连接中,我将它命名为连接A,参见列表C,然后,剪切并粘贴这部分SQL Server代码到另外一个连接,我将它命名为连接B,参见列表D。
BEGIN TRANSACTION
      UPDATE DeadlockTable2
      SET DeadlockValue2 = 'Connection1'
      WAITFOR DELAY '0:0:3'
      UPDATE DeadlockTable1
      SET DeadlockValue1 = 'Connection1'
COMMIT TRANSACTION
列表C
BEGIN TRANSACTION
      UPDATE DeadlockTable1
      SET DeadlockValue1 = 'Connection2'
      WAITFOR DELAY '0:0:6'
      UPDATE DeadlockTable2
      SET DeadlockValue2 = 'Connection2'
COMMIT TRANSACTION
列表D
为 了制造死锁,您需要首先运行连接A中的代码,紧接着运行连接B中的代码,正如连接A中WAITFOR DELAY语句所示的那样,您大约有3秒钟的时间来切换连接并执行连接B中的代码。如果您正确执行了以上步骤,那将会在一个查询窗口中收到和下面这条信息 非常相似的出错信息:
Server: Msg 1205, Level 13, State 50, Line 1
Transaction (Process ID 53) was deadlocked on
resources with another process
and has been chosen as the deadlock victim. Rerun the transaction.
发 生死锁是因为两个连接之间发生了资源争夺,连接A锁定了DeadlockTable2并试图更新DeadlockTable1,而这是无法实现的,因为与 此同时,连接B锁定了DeadlockTable1,而且需要在DeadlockTable2上运行更新语句,这个场景是一个非常经典的例子,这也是为什 么在设计事务的时候,您要尽可能按照相同的使用顺序来更新表格,这一点非常重要。
如果您按照这种方式来设计事务,那么出现这种令人头疼的情况的可能性就会降低很多。SQL Server数据库引擎有专门的算法来通知您有这种情况出现,它还会系统性地关闭一个进程并允许另外一个顺利完成。
现 在我们已经体验了死锁,我们可以使用SQLDiag工具将错误信息输出到一个文本文件了。您可能会感到奇怪,既然在出现死锁错误的情况下可以从屏幕上看到 错误信息,为什么还要将这些信息输出到文本文件中呢?开启追踪标记可以捕获在您的系统上发生的所有死锁,这对于有大量数据更新的系统来说,这些信息是非常 有价值的。在文本文件中查找并观察何时发生错误、哪些对象牵连在错误中,可以节省您大量的研究时间。
为了执行SQLDiag工具,打开一个命令提示符窗口并浏览到SQL Server安装目录中的Binn文件夹。一个可能出现该工具的文件夹是C:Program FilesMicrosoft SQL ServerMSSQLBinn。
在使用这个工具的时候,您可能会用到一些参数,我会用到-E和-O开关,-E的含义是在执行是使用集成的安全属性;而-O开关可以指定您要输出的文件路径,以下是使用该工具参数的一个例子:
C:Program FilesMicrosoft SQL ServerMSSQLBinn
SQLDiag –E –O C:SQLDiagOutput.txt
[b]Conclusion[/b]
死 锁,尤其在2005版之前的SQL Server中,常常是数据库管理员的致命伤,如果没有好的方法来捕获并重现死锁事件,数据库管理员和开发者不得不依赖SQL Profiler和其它的工具来捕获死锁,并用于进一步的研究工作。SQLDiag是一个非常有效的追踪工具,不仅可以用来对付这些令人尴尬的死锁错误, 还可以用来捕获SQL Server环境中很多其它的诊断信息。我建议您要花些时间来研究这个强大的工具,而不仅仅是尝试本文中的例子,因为SQLDiag可以作为预防性的工具 来避免未来可能出现的令人头痛的问题。

No comments: