数据库死锁分析与解决

article/2025/8/26 18:47:41

一、死锁的表现

1、错误信息是:事务(进程 ID)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务。

2、错误信息是:事务(进程 ID )与另一个进程被死锁在 锁 | 通信缓冲区 资源上,并且已被选作死锁牺牲品。请重新运行该事务。

二、死锁的原因

1、由于多用户、多任务的并发性和事务的完整性要求,当多个事务处理对多个资源同时访问时,若双方已锁定一部分资源但也都需要对方已锁定的资源时,无法在有限的时间内完全获得所需的资源,就会处于无限的等待状态,从而造成其对资源需求的死锁。

2、数据库本身加锁机制的实现方法不同,各数据库系统也会产生其特殊的死锁情况。如在Sybase SQL Server 11 中,最小锁为 2K
一页的加锁方法,而非行级锁。如果某张表的记录数少且记录的长度较短(即记录密度高,如应用系统中的系统配置表或系统参数表就属于此类表),被访问的频率高,就容易在该页上产生死锁。

表现一:
一个用户 A 访问表 A(锁住了表 A),然后又访问表 B。另一个用户 B 访问表 B(锁住了表 B),
然后企图访问表 A。这时用户 A 由于用户 B 已经锁住表 B,它必须等待用户 B 释放表 B,
才能继续,同样用户 B 要等用户 A 释放表 A 才能继续操作,这样就造成了死锁。

解决方法:
这种死锁是由于程序的 BUG 产生的,需调整程序对数据库层的实现逻辑。仔细分析程序的逻辑:
(1)尽量避免同时锁定两个资源。
(2)必须同时锁定两个资源时,要保证在任何时刻都应该按照相同的顺序来锁定资源。

表现二:
用户 A 读一条纪录,然后修改该条纪录,同时用户 B 也修改该条纪录。这里用户 A 的事务里锁的性质由共享锁企图上升到独占锁 (for update),而用户 B 里的独占锁由于 A 有共享锁存在所以必须等 A 释放掉共享锁,而 A 由于 B 的独占锁而无法上升的独占锁也就不可能释
放共享锁,于是出现了死锁。这种死锁比较隐蔽,但其实在稍大点的项目中经常发生。

解决方法:
让用户 A 的事务(即先读后写类型的操作),在 select 时就是用 update lock。
语法如下:select * from table1 with(updlock) where ….

三、常见死锁情况及解决方法

1、不同的存储过程、触发器、动态 SQL 语句段按照不同的顺序同时访问多张表。

在系统实现时应规定所有存储过程、触发器、动态 SQL 语句段中,对多张表的操作总是使用同一顺序。如:有两个存储过程 procedure1、procedure2,都需要访问三张表 table1、table2
和 table3,如果 procedure1 按照 table1、table2 和 table3 的顺序进行访问,那么,procedure2也应该按照以上顺序访问这 3 张表。

2、在交换期间添加记录频繁的表,但在该表上使用了非群集索引(non-clustered)。

对在交换期间添加记录频繁的表,使用群集索引(clustered),以减少多个用户添加记录到该表的最后一页上,在表尾产生热点,造成死锁。这类表多为往来账的流水表,其特点是在交换期间需要在表尾追加大量的记录,并且对已添加的记录不做或较少做删除操作。

3、表中的记录少,且单条记录较短,被访问的频率较高。

对单张表中记录数不太多,且在交换期间 select 或 update 较频繁的表可使用设置每页最大行的办法,减少数据在表中存放的密度,模拟行级锁,减少在该表上死锁情况的发生。这类表多为信息繁杂且记录条数少的表。
如:系统配置表或系统参数表。在定义该表时添加如下语句: with max_rows_per_page=1

4、整张表被访问的频率高(如代码对照表的查询等)。

在存储过程、触发器、动态 SQL 语句段中,若对某些整张表 select 操作较频繁,则可能在
该表上与其他访问该表的用户产生死锁。对于检查账号是否存在,但被检查的字段在检查期间不会被更新等非关键语句,可以采用在 select 命令中使用 at isolation read uncommitted 子句的方法解决。该方法实际上降低了 select 语句对整张表的锁级别,提高了其他用户对该表
操作的并发性。在系统高负荷运行时,该方法的效果尤为显著。
例如: select*from titles at isolation read uncommitted

5、对流水号一类的顺序数生成器字段,可以先执行 update 流水号字段+1,然后再执行 select
获取流水号的方法进行操作。

备注:

NOLOCK(不加锁):此选项被选中时,SQL Server 在读取或修改数据时不加任何锁。在这种情况下,用户有可能读取到未完成事务(Uncommitted Transaction)或回滚(Roll Back)中数据,即所谓的“脏数据”。

UPDLOCK(修改锁):此选项被选中时,SQL Server 在读取数据时使用修改锁来代替共享锁,并将此锁保持至整个事务或命令结束。使用此选项能够保证多个进程能同时读取数据但只有该进程能修改数据。

四、死锁监控与查看

1、可通过服务器操作系统自带的“性能”工具或 LoadRunner 等第 3 方性能测试工具,添加
性能计数器 Number of Deadlocks/sec (SQLServer|Locks _Total)进行监控。
这里写图片描述
4.1 系统自带的“性能”工具监控图
这里写图片描述

4.2 LoadRunner 性能测试工具监控图

2、发生死锁后可通过如下存储过程查看详细的死锁信息,如下所示:

//死锁详细信息打印.txt

-------------------------------------------------------------------------
引起数据库死锁的是: 71 进程号,其执行的 SQL 语法如下
EventType Parameters EventInfo
-------------- ---------- ------------------------------------------------
Language Event 0
select * from test
insert test values(1,2)
(所影响的行数为 1 行)
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
--------------------------------------------------------------------------------------------------
进程号 SPID:64 被进程号 SPID:71 阻塞,其当前进程执行的 SQL 语法如下
EventType Parameters EventInfo
-------------- ---------- -------------------------------------------------------------------------
Language Event 0
select * from test
insert test values(1,2)
(所影响的行数为 1 行)
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
---------------------------------------------------------------------------------------------------

//数据库里阻塞和死锁情况查看.sql

```
/********************************************************
// 创建 :
// 日期 :
// 修改 :
// 作者 :
// 说明 : 查看数据库里阻塞和死锁情况
********************************************************/
use master
go
CREATE procedure sp_who_lock
as
begin
declare @spid int,@bl int,
@intTransactionCountOnEntry int,
@intRowcount int,
@intCountProperties int,
@intCounter int
create table #tmp_lock_who (
id int identity(1,1),
spid smallint,
bl smallint)
IF @@ERROR<>0 RETURN @@ERROR
insert into #tmp_lock_who(spid,bl) select 0 ,blocked
from (select * from sysprocesses where blocked>0 ) a
where not exists(select * from (select * from sysprocesses
where blocked>0 ) b
where a.blocked=spid)
union select spid,blocked from sysprocesses where blocked>0
IF @@ERROR<>0 RETURN @@ERROR
-- 找到临时表的记录数
select @intCountProperties = Count(*),@intCounter = 1
from #tmp_lock_who
IF @@ERROR<>0 RETURN @@ERROR
if @intCountProperties=0
select '现在没有阻塞和死锁信息' as message
-- 循环开始
while @intCounter <= @intCountProperties
begin
-- 取第一条记录
select @spid = spid,@bl = bl
from #tmp_lock_who where Id = @intCounter
begin
if @spid =0
select '引起数据库死锁的是: '+ CAST(@bl AS VARCHAR(10))
+ '进程号,其执行的 SQL 语法如下'
else
select '进程号 SPID:'+ CAST(@spid AS VARCHAR(10))+ '被'
+ '进程号 SPID:'+ CAST(@bl AS VARCHAR(10)) +'阻塞,其当前进程执行的 SQL 语法如下'DBCC INPUTBUFFER (@bl )
end
-- 循环指针下移
set @intCounter = @intCounter + 1
end
drop table #tmp_lock_who
return 0
end
GO

五、死锁现象重现与模拟

1、驱动数据构造

一般对于事务性死锁,均产生在事务性操作(同时对同一表进行读和写操作)中。所以,首
先需构造驱动数据,满足相应操作条件(where 或 if 中判断条件),模拟对同一张表的读和
写操作。

2、并发性模拟

由于死锁产生在对表操作的同一时刻,所以可以借助第三方支持并发测试的工具来实现(例
如:LoadRunner)。当然也可以采用单元测试的方式实现,即在数据库层调用同一存储过程,
然后使用无限循环调用的方式进行模拟。

六、关于死锁的预防建议(个人总结)

1、优化索引
2、对所有的报表,非事务性的 select 语句 在 from 后都加了 with (nolock) 语句
3、对所有的事务性更新尽量使用相同的更新顺序来执行


http://chatgpt.dhexx.cn/article/X0ff6oZr.shtml

相关文章

数字 IC 技能拓展(1)Xilinx_Vivado_SDK_2019.1 安装详细教程

引言 工欲善其事必先利其器&#xff0c;而君之“器”尚无&#xff0c;就更别谈“事”了。赶紧&#xff01;我们需要下载并安装一个 Xilinx Vivado 软件&#xff01;&#xff01;接下来就飞速地开始我们的 Xilinx_Vivado_SDK_2019.1 详细安装教程&#xff01;&#xff01;&#…

win10安装vivado + vitis 2019.2 教程

win10安装vivado vitis 2019.2 教程 安装包&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1fPlNDzpC0EPXMhOloDyzfA 提取码&#xff1a;1234 网上其他博主的安装教程&#xff0c;比如&#xff1a;vivado2019.2的安装&#xff0c;最后是没有安装上vitis PS端开发软件…

vivado入门教程

vivado入门教程 基本步骤例程实现 第一次写博客&#xff0c;也是第一次使用vivado&#xff0c;自己也在学习之中&#xff0c;欢迎大家的评论啊&#xff01; 基本步骤 一、新建工程 二、选择工程路径及命名 三、一路next到下图&#xff0c;确定芯片的型号 四、添加源文件 五…

手把手教你安装vivado2015.4开发环境

//vivado2015.4安装教程 //作者&#xff1a;紫菜蛋花汤 //时间&#xff1a;2018.7.8 //版本&#xff1a;V1 准备工作&#xff1a; 1.vivado2015.4安装包 官方下载压缩包文件名&#xff1a;Xilinx_Vivado_SDK_2015.4_1118_2.tar 个人百度云连接&#xff1a;https://pan.ba…

Vivado 2015.4 安装教程(含license)

首先先下载vivado2015.4的压缩文件&#xff0c;可以从网盘里下载&#xff1a; 百度网盘链接&#xff1a;点击链接 下载后解压&#xff1a; 点击xsetup.exe文件 点击Next 点击Next 一定要选择第一个Vivado HL WebPack&#xff0c;不要像图中那样选择第三个&#xff0c;因为第一…

vivado 2017.4安装步骤

目录&#xff1a;windows安装vivado2017.4&#xff1b;虚拟机ubuntu安装vivado 2017.4&#xff1b;ios安装vivado。 一&#xff0c;windows安装vivado2017.4 xilinx官网下载地址为&#xff1a;https://www.xilinx.com/support/download.html 下载完解压后&#xff0c;如图所示…

vivado2019.2安装+license添加教程

vivado2019.2安装license添加教程 注意&#xff1a; 1.电脑的账户名字一定是英文&#xff1b; 2.压缩文件夹有30个G&#xff0c;安装后会更大&#xff0c;需要预留足够的空间。 1.资源链接 百度网盘: https://pan.baidu.com/s/1xEuB-vzoXWpj40fd1wAEFg 密码&#xff1a;tkk1…

[Software]Vivado 2018.2 安装及激活教程

一、安装 1、 解压文件 注&#xff1a;要将压缩文件解压至无中文的路径中。 2、 双击“xsetup.exe”文件&#xff0c;开始安装 3、 不选择新版本&#xff0c;选择继续安装此版本 4、 点击“Next”出现协议&#xff0c;在“I Agree”前都打勾 5、 版本选择&#xff0c;用户可以…

Vivado的下载和安装

本文是自己在安装和使用vivado的一个简单记录。 在安装之前进入官网下载好自己需要版本的安装包&#xff0c;软件安装包比较大&#xff0c;需要花费比较长的一段时间。 vivado官网下载地址 &#xff1a;下载地址 安装好软件后需要使用到license文件&#xff0c;可以去官网申…

Vivado2021.2版本安装教程

Vivado2021.2版本安装教程 2021.2版本提取链接&#xff1a;https://pan.baidu.com/s/12P7twkEVErKmqTmkhTnvMg 提取码&#xff1a;2hyr。 第一步&#xff1a;首先打开解压好的软件&#xff0c;找到xsetup.exe,然后管理员模式运行&#xff0c;出现以下界面&#xff0c;点击Next。…

Vivado安装教程详细版

之前问过大佬&#xff0c;哪个版本的vivado更加稳定&#xff0c;大佬说2017.4&#xff0c;于是俺就安装了一个。 安装步骤&#xff1a; 关闭360等杀毒软件。 下载解压后&#xff0c;双击打开这个xsetup程序&#xff1a; 弹出 点击Continue 三个I Agree全部勾选&#xff0c;…

Vivado 2018.3 安装步骤及 license 获取

本文的主要内容是介绍 Vivado 2018.3 版本的安装步骤及其 license 的获取与加载。 首先下载安装包&#xff0c;将其在没有中文的路径下解压。注意在解压前最好关闭电脑的杀毒软件&#xff0c;防止某些文件被拦截或者删除&#xff01; 解压完成后打开文件夹&#xff0c;在最底部…

Vivado的安装以及使用_入门

Vivado的安装以及使用 零. Vivado简要介绍 Vivado是FPGA厂商赛灵思提供的一款EDA&#xff08;Electronic Design Automation&#xff09;工具. 在电子设计自动化方面, 其主要提供了四种功能: RTL代码编写, 功能仿真, 综合(synthesis)以及实现(implementation). 其中, RTL代码…

Vivado安装—Xilinx design tool already exists for 2019.1,specify a different program program group entr

V i v a d o 重 新 安 装 出 现 问 题 &#xff1f; {\color{Red}Vivado重新安装出现问题&#xff1f;} Vivado重新安装出现问题&#xff1f; V i v a d o 重 新 安 装 出 现 问 题 &#xff1f; {\color{Red}Vivado重新安装出现问题&#xff1f;} Vivado重新安装出现问题&…

vivado2017.4安装教程

安装前先关闭杀毒软件和360卫士&#xff0c;注意安装路径不能有中文&#xff0c;存放安装包的路径最好也不要有中文。 1、解压安装包到当前文件夹 2、运行安装程序。 3、提示下载最新的版本&#xff0c;不要下载&#xff0c;点击Continue,然后点击next。 4、点击I Agree&#x…

vivado快速下载及解压安装教程

vivado快速下载及解压安装教程 一&#xff0c;登录中文版官网 网址 https://china.xilinx.com link 滑动至页面下方产品支持类目点击下载与许可 选择想要下载的版本&#xff0c;初学者建议下载和所要用的教程视频一致的版本或每一年的最后一版最为稳定。 如要下载更早的版本…

FPGA学习——Vivado2017.4安装教程

为方便大家正常学习&#xff0c;提供了Vivado2017.4软件的安装及破解教程&#xff0c;供大家参考。 1、Vivado2017.4安装包下载解压完成后&#xff0c;如下图所示&#xff0c;Linux系统执行蓝色框线&#xff08;xsetup&#xff09;&#xff0c;Windows系统双击执行红色框线&am…

Xilinx_Vivado_2019.1下载和安装教程

一、vivado2019.1下载和安装教程 1、首先要下载安装包&#xff0c;建议直接在Xilinx官网下载&#xff1a;https://www.xilinx.com/support/download.html。选择我们需要安装的安装包&#xff08;其他版本也是这样&#xff0c;需要选择支持所有OS的安装包&#xff09;&#xff…

Vivado18.3的安装 安装教程

本文内容学习自【ALINX】FPGA ZYNQ视频教程——AX7010/AX7020教程——基础部分 1.Vivado18.3的下载 Vivado18.3是18年的最后一个版本&#xff0c;正常来讲每年的最后一个版本即为相对稳定的版本。 百度网盘:https://pan.baidu.com/s/1PiQO1BeLSZNFn_BrqanyFw 提取码&#x…

vivado.2019.1 安装教程

vivado.2019.1 安装教程 下载链接&#xff1a; VIVADIO 2019.1 链接&#xff1a;https://pan.baidu.com/s/17_cPUahNzHmm-3xKsKQ7GQ 提取码&#xff1a;rop0 –来自百度网盘超级会员V4的分享 1、解压所有文件 所有的文件不能有中文名和空格 解压part1 所有的分卷就会自动解压…