RDS SQL Server死锁(Deadlock)系列之一使用DBCC捕获死锁

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: RDS SQL Server死锁(Deadlock)系列之一使用DBCC捕获死锁http://www.bieryun.com/4528.html 问题引入 在日常运维阿里云RDS SQL Server产品过程中,经常会被客户问道:“应用程序被死锁报错啦?影响很大,到底是哪个进程导致了死锁发生的啊?怎么解决啊?怎么办呀?”。


问题引入

在日常运维阿里云RDS SQL Server产品过程中,经常会被客户问道:“应用程序被死锁报错啦?影响很大,到底是哪个进程导致了死锁发生的啊?怎么解决啊?怎么办呀?”。从客户一连串的问题中,我们深刻体会到了死锁问题的紧迫性和影响之大。授人予鱼而不如授人予渔,RDS SQL Server死锁系列文章就是为了帮助客人彻底解决死锁问题为初衷而诞生的。本篇文章是系列文章的开篇,主要是讨论如何使用DBCC来捕获死锁信息,内容包括:
DBCC捕获死锁
死锁测试
死锁分析
解决方法

DBCC捕获死锁

DBCC捕获死锁是利用了SQL Server死锁自动监测机制(默认每5秒运行一次)的返回信息,来将死锁信息记录到数据库日志记录中,我们可以事后从错误日中来查看这些有用的死锁信息,包括:
死锁的牺牲进程
死锁发生时的进程信息
死锁发生时争抢的资源
其实,DBCC捕获死锁信息的方法本身非常简单,只需要使用DBCC命令打开两个跟踪标记(1222和1204)即可。方法如下:

USE master
GO

DBCC TRACEON(1222,-1)
GO

--also write like this, that’s fine to use any one 
DBCC TRACEON (1204, 1222, -1)
GO

跟踪标记打开后,我们可以使用下面的语句再次检查,确保标记打开成功:

DBCC TRACESTATUS(-1)
GO

截图如下所示:
01.png

在这里也顺便把如何关闭死锁跟踪标记的方法写到这里:

DBCC TRACEOFF (1204, 1222, -1)
GO

--split into two stats
DBCC TRACEOFF (1204,-1)
GO
DBCC TRACEOFF (1222,-1)
GO

死锁测试

获取死锁信息的跟踪标记已经打开,接下来进行死锁测试。首先,在Test数据库下创建两个测试表,表名分别为:dbo.test_deadlock1和dbo.test_deadlock2,代码如下:

IF DB_ID('Test') IS NULL
    CREATE DATABASE Test;
GO

USE Test
GO

-- create two test tables
IF OBJECT_ID('dbo.test_deadlock1','u') IS NOT NULL
    DROP TABLE dbo.test_deadlock1
GO

CREATE TABLE dbo.test_deadlock1(
id INT IDENTITY(1,1) not null PRIMARY KEY
,name VARCHAR(20) null
);

IF OBJECT_ID('dbo.test_deadlock2','u') IS NOT NULL
    DROP TABLE dbo.test_deadlock2
GO

CREATE TABLE dbo.test_deadlock2(
id INT IDENTITY(1,1) not null PRIMARY KEY
,name VARCHAR(20) null
);

INSERT INTO dbo.test_deadlock1
SELECT 'AA'
UNION ALL
SELECT 'BB';


INSERT INTO dbo.test_deadlock2
SELECT 'AA'
UNION ALL
SELECT 'BB';
GO

接下来,我们使用SSMS打开一个新的连接,我们假设叫session 1,执行如下语句:

--session 1
USE Test
GO

BEGIN TRAN 
UPDATE dbo.test_deadlock1
SET name = 'CC'
WHERE id = 1
;
WAITFOR DELAY '00:00:05'

UPDATE dbo.test_deadlock2
SET name = 'CC'
WHERE id = 1
;
ROLLBACK

紧接着,我们使用SSMS打开第二个连接,假设叫Session 2,执行下面的语句:

--session 2
USE Test
GO

BEGIN TRAN 
UPDATE dbo.test_deadlock2
SET name = 'CC'
WHERE id = 1
;

UPDATE dbo.test_deadlock1
SET name = 'CC'
WHERE id = 1
;
COMMIT

一段时间以后,你会发现Session 2执行的语句会被死锁,做为了死锁的牺牲品,错误信息如下:

Msg 1205, Level 13, State 51, Line 11
Transaction (Process ID 62) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

截图为证:
02.png

死锁分析

死锁场景,我们已经模拟出来了,接下来就是分析死锁的时候了。让我们查看错误日志:

EXEC sys.sp_readerrorlog

截图如下所示:
03.png

从这个死锁信息中,我们不难发现几个非常有用的信息:
参与死锁的进程(process-list):锁住其他进程的进程和死锁牺牲者进程(会有deadlock victim标记)。
死锁发生时,进程执行的语句(inputbuf):这个很重要,找到了语句就可以针对死锁的语句进行针对性的优化解决。
进程争抢的资源(resource-list):死锁发生时,到底进程之间在争抢什么资源,死锁的类型是什么?本例资源争抢发生在表Test.dbo.test_deadlock1 的主键上indexname=PK__test_dea__3213E83F07020F21,死锁类型为X锁(排他锁)。

解决方法

通过SQL Server错误日志中死锁信息的分析,我们可以从死锁发生时进程执行的语句发现,死锁发生的原因是两个UPDATE进程操作的表顺序不一致导致的。我们只需要调整其中一个进程的UPDATE表顺序即可解决这个死锁问题。比如,调整Session 2的执行语句,如下:

--session 2
USE Test
GO

BEGIN TRAN 
UPDATE dbo.test_deadlock1
SET name = 'CC'
WHERE id = 1
;

UPDATE dbo.test_deadlock2
SET name = 'CC'
WHERE id = 1
;
COMMIT

最后总结

本篇分享讲解了使用DBCC命名捕获SQL Server死锁信息,是RDS SQL Server死锁系列文章的开篇,我们还会在后续系列文章分享更多的方法来捕获死锁信息,敬请期待。

原文地址https://yq.aliyun.com/articles/73856

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
19天前
|
SQL 人工智能 算法
【SQL server】玩转SQL server数据库:第二章 关系数据库
【SQL server】玩转SQL server数据库:第二章 关系数据库
61 10
|
2月前
|
SQL 数据库 数据安全/隐私保护
Sql Server数据库Sa密码如何修改
Sql Server数据库Sa密码如何修改
|
29天前
|
SQL
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
30 0
|
27天前
|
SQL 关系型数据库 MySQL
SQL Error (2013): Lost connection to MySQL server at 'waiting for initial communication packet', sys...
SQL Error (2013): Lost connection to MySQL server at 'waiting for initial communication packet', sys...
|
19天前
|
SQL 算法 数据库
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
91 6
|
6天前
|
SQL 数据管理 关系型数据库
如何在 Windows 上安装 SQL Server,保姆级教程来了!
在Windows上安装SQL Server的详细步骤包括:从官方下载安装程序(如Developer版),选择自定义安装,指定安装位置(非C盘),接受许可条款,选中Microsoft更新,忽略警告,取消“适用于SQL Server的Azure”选项,仅勾选必要功能(不包括Analysis Services)并更改实例目录至非C盘,选择默认实例和Windows身份验证模式,添加当前用户,最后点击安装并等待完成。安装成功后关闭窗口。后续文章将介绍SSMS的安装。
9 0
|
15天前
|
SQL 安全 网络安全
IDEA DataGrip连接sqlserver 提示驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接的解决方法
IDEA DataGrip连接sqlserver 提示驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接的解决方法
34 0
|
19天前
|
SQL 存储 数据挖掘
数据库数据恢复—RAID5上层Sql Server数据库数据恢复案例
服务器数据恢复环境: 一台安装windows server操作系统的服务器。一组由8块硬盘组建的RAID5,划分LUN供这台服务器使用。 在windows服务器内装有SqlServer数据库。存储空间LUN划分了两个逻辑分区。 服务器故障&初检: 由于未知原因,Sql Server数据库文件丢失,丢失数据涉及到3个库,表的数量有3000左右。数据库文件丢失原因还没有查清楚,也不能确定数据存储位置。 数据库文件丢失后服务器仍处于开机状态,所幸没有大量数据写入。 将raid5中所有磁盘编号后取出,经过硬件工程师检测,没有发现明显的硬件故障。以只读方式将所有磁盘进行扇区级的全盘镜像,镜像完成后将所
数据库数据恢复—RAID5上层Sql Server数据库数据恢复案例