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

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
简介: 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

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
SQL 关系型数据库 MySQL
mysql 简单的sql语句,入门级增删改查
介绍MySQL中的基本SQL语句,包括数据的增删改查操作,使用示例和简单的数据表进行演示。
mysql 简单的sql语句,入门级增删改查
|
1月前
|
SQL 关系型数据库 MySQL
|
22天前
|
SQL 运维 关系型数据库
MySQL 运维 SQL 备忘
MySQL 运维 SQL 备忘录
44 1
|
1月前
|
SQL 存储 关系型数据库
SQL文件导入MySQL数据库的详细指南
数据库中的数据转移是一项常规任务,无论是在数据迁移过程中,还是在数据备份、还原场景中,导入导出SQL文件显得尤为重要。特别是在使用MySQL数据库时,如何将SQL文件导入数据库是一项基本技能。本文将详细介绍如何将SQL文件导入MySQL数据库,并提供一个清晰、完整的步骤指南。这篇文章的内容字数大约在
78 1
|
11天前
|
SQL 关系型数据库 MySQL
MySql5.6版本开启慢SQL功能-本次采用永久生效方式
MySql5.6版本开启慢SQL功能-本次采用永久生效方式
27 0
|
11天前
|
SQL 关系型数据库 MySQL
mysql编写sql脚本:要求表没有主键,但是想查询没有相同值的时候才进行插入
mysql编写sql脚本:要求表没有主键,但是想查询没有相同值的时候才进行插入
23 0
|
1月前
|
存储 SQL 关系型数据库
MySQL查询数据库锁表的SQL语句
MySQL查询数据库锁表的SQL语句
76 1
|
24天前
|
SQL 存储 关系型数据库
mysql 数据库空间统计sql
mysql 数据库空间统计sql
42 0
|
24天前
|
SQL 存储 关系型数据库
mysql SQL必知语法
本文详细介绍了MySQLSQL的基本语法,包括SELECT、FROM、WHERE、GROUPBY、HAVING、ORDERBY等关键字的使用,以及数据库操作如创建、删除表,数据类型,插入、查询、过滤、排序、连接和汇总数据的方法。通过学习这些内容,读者将能更好地管理和操
11 0
|
2月前
|
SQL 关系型数据库 MySQL
创建包含MySQL和SQLServer数据库所有字段类型的表的方法
创建一个既包含MySQL又包含SQL Server所有字段类型的表是一个复杂的任务,需要仔细地比较和转换数据类型。通过上述方法,可以在两个数据库系统之间建立起相互兼容的数据结构,为数据迁移和同步提供便利。这一过程不仅要考虑数据类型的直接对应,还要注意特定数据类型在不同系统中的表现差异,确保数据的一致性和完整性。
32 4
下一篇
无影云桌面