日期:2015-06-28 00:00:00 来源: IT猫扑网
本文将为大家讲的是SQL Server Profiler分析死锁几大步骤,这里也是为了大家更好的做好数据库的管理工作。
在两个或多个SQL Server进程中,每一个进程锁定了其他进程试图锁定的资源,就会出现死锁,例如,进程process1对table1持有1个排它锁(X),同时process1对table2请求1个排它锁(X), 进程process2对table2持有1个排它锁(X),同时process2对table1请求1个排它锁(X) 类似这种情况,就会出现死锁,除非当某个外部进程断开死锁,否则死锁中的两个事务都将无限期等待下去。
Microsoft SQL Server 数据库引擎死锁监视器定期检查陷入死锁的任务。
如果监视器检测到循环依赖关系,将选择其中一个任务作为牺牲品(通常是选择占资源比较小的进程作为牺牲品),然后终止其事务并提示错误1205。
这里我们通过SQL Server Profiler来监视分析死锁的发生过程,那样我们就会深刻理解死锁的成因。
1.创建测试表。
在 Microsoft SQL Server Management Studio上,新建一个查询,写创建表DealLockTest_1 & DealLockTest_2两个表:
脚本:
- useTest
- --创建分析死锁使用到的两个表DealLockTest_1&DealLockTest_2
- go
- SetNocountOn
- Go
- ifobject_id('DealLockTest_1')IsNotNull
- DropTableDealLockTest_1
- go
- CreateTableDealLockTest_1
- (
- IDintIdentity(1,1)PrimaryKey,
- Namenvarchar(512)
- )
- ifobject_id('DealLockTest_2')IsNotNull
- DropTableDealLockTest_2
- go
- CreateTableDealLockTest_2
- (
- IDintIdentity(1,1)PrimaryKey,
- Namenvarchar(512)
- )
- Go
- InsertIntoDealLockTest_1(Name)
- SelectnameFromsys.all_objects
- InsertIntoDealLockTest_2(Name)
- SelectnameFromsys.all_objects
- Go
创建好表和插入测试数据后,先执行脚本代码(因为我们不需要跟踪该代码),紧接着,我们就模拟两个会话,一个会话里面包含一个事务。这里我们就新建两个查询,其中第一个会话,是更新DealLockTest_1表后,等待5秒钟,更新DealLocktest_2.
- UseTest
- Go
- --第一个会话
- BeginTran
- UpdateDealLockTest_1
- SetName=N'test1'
- WhereID>0
- /*这里的Waitfor等待,是为了容易获取死锁的发生*/
- WaitforDelay'00:00:05'
- UpdateDealLockTest_2
- SetName=N'test2'
- WhereID>0
- CommitTran
- Go
代码写好后,我们先不要执行代码,接下来就写第二个会话代码; 第二个会话更新表的顺序,刚好与第一个会话相反,是更新DealLockTest_2表后,等待5秒钟,更新DealLocktest_1.
- UseTest
- Go
- --第二个会话
- BeginTran
- UpdateDealLockTest_2
- SetName=N'test1'
- WhereID>0
- /*这里的Waitfor等待,是为了容易获取死锁的发生*/
- WaitforDelay'00:00:05'
- UpdateDealLockTest_1
- SetName=N'test2'
- WhereID>0
- CommitTran
- Go
第二个会话代码,也先不要执行。
2.启动SQL Server Profiler,创建Trace(跟踪).
启动SQL Server Profiler工具(在Microsoft SQL Server Management Studio的工具菜单上就发现它),创建一个Trace,Trace属性选择主要是包含:
Deadlock graph Lock: Deadlock Lock: Deadlock Chain RPC:Completed SP:StmtCompleted SQL:BatchCompleted SQL:BatchStarting
点执行按钮,启动Trace。
3.执行测试代码&监视死锁。
转到 Microsoft SQL Server Management Studio界面,执行第一个会话&第二个会话的代码,稍稍等待5秒钟,我们就会发现其中一个会话收到报错消息
我们再切换到SQL Server Profiler界面,就能发现SQL Server Profiler收到执行脚本过程发生死锁的信息。
OK,这里就先停止SQL Server Profiler上的"暂停跟踪" Or "停止跟踪"按钮,下面我们具体分析死锁发生过程。
4.分析死锁
如下图,我们可以看到第一个会话在SPID 54,第二个会话在SPID 55,一旦SQL Server发现死锁,它就会确定一个优胜者,可成功执行,和另一个作为牺牲品,要回滚。
可以到看到EventClass列中,两条SQL:BatchCompleted事件紧跟在Lock:DealLock后面,其中一条,它就是作为牺牲品,它会被回滚.而另一条SQL:BatchCompleted将会是优胜者,成功执行。
那么,谁是优胜者,谁是牺牲品呢? 不用着急,通过DealLock graph事件,所返回来的信息,我们可以知道结果。
我们虽然不能明白DealLock graph图示的含义,但通过图中描述的关系,我们知道一些有用的信息。图中左右两旁椭圆形相当一个处理节点(Process Node),当鼠标移动到上面的时候,可以看到内部执行的代码,如Insert,UPdate,Delete.有打叉的左边椭圆形就是牺牲者,没有打叉的右边椭圆形是优胜者。中间两个长方形就是一个资源节点(Resource Node),描述数据库中的对象,如一个表、一行或一个索引。在我们当前的实例中,资源节点描述的是,在聚集索引请求获得排它锁(X)。椭圆形与长方形之间,带箭头的连线表示,处理节点与资源节点的关系,包含描述锁的模式.
接下来我们更详细的看图里面的数据说明。
先看右边作为优胜者的这椭圆形,我们可以看到内容包含有:
服务器进程 ID: 服务器进程标识符 (SPID),即服务器给拥有锁的进程分配的标识符。服务器批 ID: 服务器批标识符 (SBID)。执行上下文 ID: 执行上下文标识符 (ECID)。与指定 SPID 相关联的给定线程的执行上下文 ID。ECID = {0,1,2,3, ...n},其中 0 始终表示主线程或父线程
相关文章
相关下载
网友评论