sqlserver 中死锁相关问题

死锁定义:

所谓死锁就是两个线程或多个线程在拥有一部分资源的同时还需要拥有其他资源,

但是其他资源被其他线程占有,每个线程为了获得其他线程占有的资源都处于一个相互等待

的状态,这个时候如果没有外界力量破坏这种相互等待的状态或是某个(些)线程自动放弃已经占有的资源,

那么所有的线程都无法完成任务,这个时候系统处于一个僵死状态。这就是所谓的死锁。

sqlserver自身有个锁监视器(Lock monitor),一旦发现死锁,SqlServer会kill掉一个其中一个线程,

使另外一个(些)继续完成任务。该死锁监视器是以一个后台线程的形式存在的,

可以通过系统视图sys.dm_exec_requests查看

select * from sys.dm_exec_requests

where session_id  < 50

但是仅仅依靠SqlServer自身的死锁监视器来解决死锁是不行的,虽然SqlServer暴力解决了死锁的问题

但是这种的暴力解决会影响系统的性能的,对于高并发的性能是不可取的。

接下来来了解下死锁的常见形式,弄清楚产生死锁的原因,然后再通过重写sql或是创建索引或是修改业务逻辑

来解决死锁问题。

创建测试表和数据

create table testklup

(

clskey int not null,

nlskey int not null,

cont1  int not null,

cont2  char(3000)

)

create unique clustered index inx_cls on testklup(clskey)

create unique nonclustered index inx_nlcs  on testklup(nlskey) include(cont1)

insert into testklup select 1,1,100,‘aaa‘

insert into testklup select 2,2,200,‘bbb‘

insert into testklup select 3,3,300,‘ccc‘

死锁的几种表现形式

1.数据行的争用

会话一:

begin tran

select * from dbo.testklup with(updlock)

where clskey=1

waitfor delay ‘00:00:10‘

update dbo.testklup

set cont1=200

where clskey=2

会话二:

begin tran

select * from dbo.testklup with(updlock)

where clskey=2

waitfor delay ‘00:00:10‘

update dbo.testklup

set cont1=200

where clskey=1

先执行会话一,然后执行会话二 ,会出现如下死锁相关信息

产生死锁的原因:

会话一先对clskey=1的数据行添加了一个更新锁,然后它想要对

clskey=2的数据行添加排它锁,但是这个时候clskey=2已被会话二添加了

共享锁,会话二还想对clskey=1 对添加排它锁,但是clskey=1已经被会话一添加了 共享锁.

解决方法:例一种的产生死锁的原因很简单就是没有按照一个固定的顺序访问数据库中的对象,

解决此类死锁问题就需要修改业务逻辑或是sql语句了,按照一个固定的顺序访问数据库中的对象

2.键值的争用。这种争用我理解了很久才弄明白

会话一:

declare @i int

set @i=100

while 1=1

begin

update testklup  set [email protected]

where clskey=1

set @[email protected]+1

end

执行计划如下:

会话二:

declare @cont2 char(3000)

while 1=1

begin

select @cont2=cont2 from testklup  where nlskey=1

end

执行计划如下:

先执行会话一再执行会话二 ,结果如下:

产生死锁的原因:

会话一根据主键clskey=1找到数据行后在数据行添加了一个更新锁(U),找到数据后,准备修改数据,

更新锁转换为排它锁(X),在更新完表数据后再去更新非聚集索引中的列(cont1)

(create unique nonclustered index inx_nlcs  on testklup(nlskey) include(cont1)) ,

所以会话一会对非聚集索引添加排它锁,完成数据的更新。

再看会话二,会话二走非聚集索引获得目标数据行的主键ID,那么会话二就会对非聚集索引添加共享锁,

当会话二获得主键ID后还要通过聚集索引获得列cont2的值,那么回话二就会对主键行添加共享锁

再看下回话一和会话二访问的数据,其实都是同一条数据,

当会话一对非聚集索引添加排它锁,会话二已经对非聚集索引添加了共享锁了,因此会话一等待会话二释放共享锁

当会话二对聚集索引添加共享锁时,会话一已经对聚集索引添加了排它锁,会话二等待会话一释放排它锁

这个时候就死锁了。

解决方案:

方案一:不让会话二访问聚集索引

那么需要修改非聚集create unique nonclustered index inx_nlcs  on testklup(nlskey) include(cont2,cont1)

方案二:不让会话一更新非聚集索引

依然需要修改非聚集索引create unique nonclustered index inx_nlcs  on testklup(nlskey)

相关参考链接:

http://www.cnblogs.com/shanksgao/p/3904662.html

时间: 2024-10-03 17:26:54

sqlserver 中死锁相关问题的相关文章

sqlserver中select造成死锁

项目上线,准备验收前出现了一个严重的问题:很多select语句作为死锁的牺牲,大部分报表无法打开.这个问题影响范围很大所有的报表都无法访问,而我们的报表是放在电视上面轮播的,电视放在工厂里面,所以出现问题后,整个工厂都知道了. 解决这个问题比较曲折,首先是写SAP接口的同事发现了问题:SAP一直在传错误数据导致产量表被锁住.修改SAP传输的错误数据后,这个死锁的问题没有出现了.但是我查看生产环境服务器日志的时候,发现这个问题依然存在,由于客户没有提这个问题,我也就是没有理由要求花时间修改了,因为

SQLServer中的死锁的介绍

原文:SQLServer中的死锁的介绍 简介      什么是死锁? 我认为,死锁是由于两个对象在拥有一份资源的情况下申请另一份资源,而另一份资源恰好又是这两对象正持有的,导致两对象无法完成操作,且所持资源无法释放. 什么又是阻塞? 阻塞是由于资源不足引起的排队等待现象.比如同时两个进程去更新一个表. 这里我们可以把阻塞作为死锁的必要条件.下面我们先理解一下死锁和阻塞再来看一下我最近遇到一个问题以及解决思路. SQLServer中的死锁      对应到SQL Server中,当在两个或多个任务

SqlServer 中 for xml path 相关

表结构: typename varchar(50) typedesc varchar(50) 示例 SQL 语句: SELECT '{"'+TypeName, '":"', TypeDesc + '"}',',' FROM dbo.SYS_DicEnumType FOR XML PATH('') 这样就可以得到一个比较接近 JSON 格式的字符串,如下: {"Gender":"性别"},{"Degree":

【SqlServer】解析SqlServer中的事务

在这篇Blog中,笔者将会解析阐述SqlServer中的事务,希望可以对你有所帮助. 1.事务是什么 事务就是单个逻辑单元执行的一系列操作.事务都具有ACID特性:原子性(Atomicity).一致性(Consistency).隔离性(Isolation)和持久性(Durability). 原子性(Atomicity):事务必须是原子工作单元:对于其数据修改,要么全都执行,要么全都不执行. 一致性(Consistency):事务在完成时,必须使所有的数据都保持一致状态. 在相关数据库中,所有规则

如何在SQLServer中处理每天四亿三千万记录

首先声明,我只是个程序员,不是专业的DBA,以下这篇文章是从一个问题的解决过程去写的,而不是一开始就给大家一个正确的结果,如果文中有不对的地方,请各位数据库大牛给予指正,以便我能够更好的处理此次业务. 项目背景 这是给某数据中心做的一个项目,项目难度之大令人发指,这个项目真正的让我感觉到了,商场如战场,而我只是其中的一个小兵,太多的战术,太多的高层之间的较量,太多的内幕了.具体这个项目的情况,我有空再写相关的博文出来. 这个项目是要求做环境监控,我们暂且把受监控的设备称为采集设备,采集设备的属性

我是如何在SQLServer中处理每天四亿三千万记录的

首先声明,我只是个程序员,不是专业的DBA,以下这篇文章是从一个问题的解决过程去写的,而不是一开始就给大家一个正确的结果,如果文中有不对的地方,请各位数据库大牛给予指正,以便我能够更好的处理此次业务. 项目背景 这是给某数据中心做的一个项目,项目难度之大令人发指,这个项目真正的让我感觉到了,商场如战场,而我只是其中的一个小兵,太多的战术,太多的高层之间的较量,太多的内幕了.具体这个项目的情况,我有空再写相关的博文出来. 这个项目是要求做环境监控,我们暂且把受监控的设备称为采集设备,采集设备的属性

SQLSERVER中如何忽略索引提示

原文:SQLSERVER中如何忽略索引提示 SQLSERVER中如何忽略索引提示 当我们想让某条查询语句利用某个索引的时候,我们一般会在查询语句里加索引提示,就像这样 SELECT id,name from TB with (index(IX_xttrace_bal)) where bal<100 当在生产环境里面,由于这个索引提示的原因,优化器一般不会再去考虑其他的索引,那有时候这个索引提示可能会导致查询变慢 经过你的测试,发现确实是因为这个索引提示的关系导致查询变慢,但是SQL服务器已经缓存

ORACLE中死锁

ORACLE中死锁的知识点总结   死锁的概念 什么是死锁呢? 其实我们生活中也有很多类似死锁的例子. 我先举一个生活中的例子:过年回家,父亲买了一把水弹枪,儿子和侄子争抢着要先玩,谁也不让谁,拆开包装后,一个抢了枪, 一个逮住了子弹和弹夹.两个都争着要先玩,但是都互不相让.结果两个人都玩不了.如果儿子要先玩,就必须让侄子把子弹和弹夹给他,如果侄子要先玩,就必须让儿子把枪给侄子.他们就这样对峙了十几分钟,互不相让. 我出来调停,让儿子把枪先给侄子玩,每个人玩十分钟.然后两个人开开心心一起玩起来.

Mysql 死锁相关操作

该随笔随时记录日常工作中遇到的关于mysql的死锁相关问题 1)查看mysql当前的处理线程(connection) mysql> show processlist; 2)杀掉对应的connection mysql> kill connection_id;    例如 kill 3(杀掉链接3) 4)查看数据库中的锁状态 mysql自带的数据库INFORMATION_SCHEMA 记录了数据库相关的信息.包括锁信息等:我们见到的了解一下. mysql> use information_s