事务与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务之详解

2018年09月08日 浏览量:198

相信大家都遇到过这个问题吧“事务与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务”。

引起这个问题主要是因为违反了事务的隔离性。


  • 隔离性:并发多个事务时,各个事务不干涉内部数据,处理的都是另外一个事务处理之前或之后的数据。

我们今天只讲解引发这一个问题的原因,关于事务其他的技术,我们今天暂不做涉猎。

接下来可复制我下面的sql语句,打开两个查询窗口,然后依次运行。



依次执行如上代码,就会出现我们今天讲解的问题

这就是因为“锁”造成的。

在执行事务的时候,如果其中有修改语句,就是更新锁,资源的更新锁一次只能分配给一个事务,如果需要对资源进行修改,更新锁会变成排他锁。

我们来分析一下上面的sql语句;

首先 我们执行左边的sql语句,执行了第一条sql语句,Dome表---延迟4秒---Domes表
然后 我们执行右边的sql语句,执行了第一条sql语句,Domes表---延迟4秒---Dome表

执行过程如下,
第一个事务更新Dome表,就为Dome表上锁;
第二个事务更新Domes表,就位Domes表上锁;
然后延迟4秒后,两个事务都要各自去更新已经上锁的表,所以这就造成了死锁,数据库发现了这种情况,就会检查选择一个合适事务作为牺牲品,牺牲品回滚数据。注意:数据库在选择牺牲品的时候,是有一套自己的判断程序的,他们会判断哪个事务更适合作为牺牲品,与执行事务的先后顺序无关,也可以设置死锁处理的优先级别,这里不多叙述。

注意:只有当事务修改的数据有冲突的时候,才会死锁,我们更新数据的时候,都是带上where条件更新某一条数据,这种情况下,只要当两个事务都是更新你指定那一条数据。才会触发死锁。

注:测试工具为Sql Server 2008R2

评论区:

昵称:
内容:
验证码:  7643