[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
- Linux下防御DDOS攻击的操作梳理
- Android新手之旅(8) ListView的使用
- 更换Ubuntu源为国内源的操作记录
- Android新手之旅(8) ListView的使用
- CKEditor/CKFinder升级心得
- Docker容器学习梳理-Dockerfile构建镜像
- 再谈web开中几种经典的大文件上传组件
- Nginx负载均衡中后端节点服务器健康检查的操作梳理
- Linux系统下CPU使用(load average)梳理
- 基于组件的.NET技术(5)
- Silverlight与WPF中BeginInvoke的差异
- Linux下部署SSH登录时的二次身份验证环境记录(利用Google Authenticator)
- Linux下DNS简单部署(主从域名服务器)
- 本地yum源部署记录
- MySQL 教程
- MySQL 安装
- MySQL 管理与配置
- MySQL PHP 语法
- MySQL 连接
- MySQL 创建数据库
- MySQL 删除数据库
- MySQL 选择数据库
- MySQL 数据类型
- MySQL 创建数据表
- MySQL 删除数据表
- MySQL 插入数据
- MySQL 查询数据
- MySQL where 子句
- MySQL UPDATE 查询
- MySQL DELETE 语句
- MySQL LIKE 子句
- mysql order by
- Mysql Join的使用
- MySQL NULL 值处理
- MySQL 正则表达式
- MySQL 事务
- MySQL ALTER命令
- MySQL 索引
- MySQL 临时表
- MySQL 复制表
- 查看MySQL 元数据
- MySQL 序列 AUTO_INCREMENT
- MySQL 处理重复数据
- MySQL 及 SQL 注入
- MySQL 导出数据
- MySQL 导入数据
- MYSQL 函数大全
- MySQL Group By 实例讲解
- MySQL Max()函数实例讲解
- mysql count函数实例
- MYSQL UNION和UNION ALL实例
- MySQL IN 用法
- MySQL between and 实例讲解
- Python随机打乱列表中的元素
- Python面试题汇总
- lldb 入坑指北(3) - 打印 c++ 实例的虚函数表
- 一文让你彻底搞懂`__str__`和`__repr__`?
- lldb 入坑指北(1) - 给Xcode批量添加启用&禁用断点功能
- Xcode 中的 Workspace、Project、Target 和 Scheme
- 学习Python一年,这次终于弄懂了浅拷贝和深拷贝
- 为速度而生的构建系统 - Ninja
- Python面试题:字符串连接
- Python面试突击
- 我半夜爬了严选的女性文胸数据,发现了惊天秘密
- 二分查找(Python实现)
- 图解JavaScript——代码实现【2】(重点是Promise、Async、发布/订阅原理实现)
- 编译器 bug 系列(1)
- 面试高频:反转链表