[SQL Server][DeakLock]观察死结的工具(一)首部曲

时间:2019-09-13
本文章向大家介绍[SQL Server][DeakLock]观察死结的工具(一)首部曲,主要包括[SQL Server][DeakLock]观察死结的工具(一)首部曲使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

最近的案子中,在测试及正式环境都碰到了几次数据库事务死结(DeadLock)而有事务被牺牲,有一次还碰上了查询事务的死结(内部平行查询死结intra-Query Parallel Deadlock),由于SQL Server发生死结(DeadLock)的原因很多,因为经验不足,自己没碰过的碰过的多,踏出解问题的第一步就是纪录死结资讯。

来笔记几种观察死结问题的工具。

  • Trace flag(1222,1204)
  • SQL Profiler
  • Extended events

我们把内容分成4篇笔记,让也是工程师的老婆轻松动手做。

第一篇先准备好死结的环境。


死结:

常见的是循环类型死结,事务彼此间使用的资源互斥却互锁,这个资源可能是各种数据对象(数据表、分页、数据列),也可能是线程、内存甚至外部资源。

发生的原因是当二个或多个事务各自具有某个资源的锁定,但事务间想尝试锁定对方事务已锁定的资源,而造成永久封锁(Blocking)导入僵局,也就是死结。简单画一个图例:

事务间陷入了僵局

  • (1)Transaction 1持有Resource1的锁定(hold),但事务尚未结束,因此准备进行下一个命令(3)。
  • (2)Transaction 2持有Resource2的锁定(hold),但事务尚未结束,因此准备进行下一个命令(4)。
  • (3)Transaction 1准备锁定Resource2,但Resource2被Transaction 2锁定,因此被暂时封锁而等待(wait)。
  • (4)Transaction 2准备锁定Resource1,但Resource1被Transaction 1锁定,因此被暂时封锁而等待(wait)。
  • 可以发现Trsnaction 1与2使用的资源有互斥(mutual exclusion),因此陷入了你等我我等你的循环等待(circular waiting)状态,没有一项工作可以继续执行,出现了死结状态。

好在这时候SQL Server会跳出来公正的仲裁,正所谓牺牲小我完成大我,SQL Server会将复原事务成本较低的事务牺牲(victim),避免僵局时间太久而让交通大打结。

Transaction 2 被迫选择牺牲(查询事务与其他更新或写入事务冲突时,查询事务的复原成本也是最低的)


循环死结:

循环死结,简单的互锁

复杂的三角关系,多个事务间的封锁僵局。


建立死结(DeadLock)的环境

为了让之后的笔记顺利完成,今天先准备环境。

1.建立死结测试所需要的数据库

CREATE DATABASE [DeadLockDb]
CONTAINMENT = NONE
ON  PRIMARY 
( NAME = N'DeadLockDb', FILENAME = N'C:tempdbDeadLockDb.mdf' , SIZE = 5120KB , FILEGROWTH = 1024KB )
LOG ON 
( NAME = N'DeadLockDb_log', FILENAME = N'C:tempdbDeadLockDb_log.ldf' , SIZE = 2048KB , FILEGROWTH = 10%)
GO

2.建立死结测试所需要的两个数据表

create table t1 
(
   c1 int identity,
   c2 varchar(30)
)
create table t2
(
   c1 int identity,
   c3 varchar(30)
)

3.建立死结测试所需要的测试数据

insert t1 VALUES('Stanley')
insert t2 VALUES('Suzie')


执行测试死结的语法

只要让两个事务互斥锁定对象时间长 (15秒)而且存取Table资源的顺序不同。

查询窗口1(先更新t1再更新t2)

BEGIN Tran Tran_one
UPDATE t1 
    set c2 = 'lock'

WAITFOR DELAY '00:00:15';  

UPDATE t2 
    set c3 = 'lock'

ROLLBACK

查询窗口2(先更新t2再更新t1):必须在15秒内执行

BEGIN Tran Tran_two

UPDATE t2 
    set c3 = 'lock'

WAITFOR DELAY '00:00:15';  

UPDATE t1
    set c2 = 'lock'

ROLLBACK

查询窗口1 x 2的执行结果:

查询窗口2出现了以下的错误消息:

消息 1205,层级 13,状态 45,行 15                                                                                                                                                                       事务 (处理序识别码 59) 在 锁定 资源上被另一个处理序锁死并已被选择作为死结的牺牲者。请重新执行该事务。

如果单就log观察,我们AP只能收到以上1205还有被牺牲的错误消息,后面我们来笔记几种观察死结的工具。


小结:

解决循环死结的方向:

  • 程序Handle 1205 Error发生后,等待几秒钟,自动重新执行。
  • 以相同的顺序来存取对象、降低锁定粒度(Table lock -> Key Lock)、使用较低的隔离层级以及降低锁定的时间(性能调校)等。


参考:

technet侦测与结束死结

https://technet.microsoft.com/zh-tw/library/ms178104(v=sql.105).aspx

Deadlocking

https://technet.microsoft.com/en-us/library/ms177433(v=sql.105).aspx

处理死结

https://technet.microsoft.com/zh-tw/library/ms177453(v=sql.105).aspx

将死结数量降至最低

https://technet.microsoft.com/zh-tw/library/ms191242(v=sql.105).aspx

原文:大专栏  [SQL Server][DeakLock]观察死结的工具(一)首部曲


原文地址:https://www.cnblogs.com/petewell/p/11516369.html