高并发update的 死锁产生原因

原创 2016年01月20日 16:58:14

在说这个之前首先了解一下讲一下update语句sql中的情况。

死锁产生的条件:

出现循环等待资源。

update对锁的流程:

       当sql发出一个update请求之后,数据库会对表中的每条记录加上U锁。然后数据库会根据where条件,将符合条件的记录转换为X锁。对不满足条件的记录释放U锁。

环境模拟

1. 创建数据库环境

--创建数据库
  create database DeadLockTest;
--创建数据表 (没有主键)
  use DealLocktest;
  create table t_table(
    A varchar(10),
    B varchar(10),
    C varchar(10)
  )
insert into  t_table values('a1','b1','c1');
insert into  t_table values('a2','b2','c2');
insert into  t_table values('a3','b3','c3');
insert into  t_table values('a4','b4','c4');
insert into  t_table values('a5','b5','c5');
insert into  t_table values('a6','b6','c6');
insert into  t_table values('a7','b7','c7');
insert into  t_table values('a8','b8','c8');
insert into  t_table values('a9','b9','c9');

创建完后,应该是这个样子:
初始环境

2.准备高并发的查询环境

因为一个人测试,很不好模拟现场的环境。所以使用sql 的waitfor 阻塞某一个查询:
A要执行的sql语句:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
 begin tran
    print convert(nvarchar(30),convert(datetime,getdate(),121),121)
       update t_table
     set A='a2'
     where B='b2'
    print convert(nvarchar(30),convert(datetime,getdate(),121),121)
    EXEC sp_lock @@spid

   waitfor  delay '00:00:05'

   update t_table
     set A='b4'
     where B='b4'
     EXEC sp_lock @@spid
    print convert(nvarchar(30),convert(datetime,getdate(),121),121)
 commit tran

B要进行的sql语句

SET TRANSACTION ISOLATION LEVEL Read UNCOMMITTED
    begin tran
  update t_table
    set A='a1'
    where B='b1'
    EXEC sp_lock @@spid
   commit tran

因为A中第一条查询和第二天查询有5s间隔,所以整个的执行过程为:
1、执行A的第一条语句 阻塞5s
2、执行B的查询
3、A的阻塞释放,要执行A的第二条语句

要执行的图解:
执行流程

分析
1、执行A的查询的时候,数据库将所有的记录加上U锁,然后将将不是c2的记录全部释放U锁。对满足条件的数据添加X锁。此时,A事务还没有结束,A不会释放此时的X锁。
2、B查询的时候,B会对表中的所有记录添加U锁,因为B查询要用到t_table这张表,B查询c1的时候,满足条件给c1添加上X锁。执行c=2的时候,要给c2加U锁,此时该记录被A添加了X锁。所以B查询需要等A释放的X锁,才可以执行。此时B等待。B要等待A释放c2的X锁
3、A的阻塞释放之后,A要进行第二条查询。这个时候A要对符合第二个查询条件的记录添加X锁。当执行c1的时候,c1刚才被B添加了X锁。所以此时A等待。A在等待B的U锁释放
结论
A在等待B释放X锁,B在等待A释放X锁。所以才会发生死锁。


解决方案:


       给查询条件加索引,原因参考下一篇详解索引

总结
       死锁的发生,肯定是因为资源的循环等待。分析死锁,就是分析这些进程分别需要等待什么资源。在sql server中 一般可以使用 sql profiler进行死锁的监控。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

高并发网站更新数据库数据比较高效的方式

看下高并发网站更新数据的方式是如何做的?如下是收集cnblogs博主的文章。 很多Web系统的瓶颈在网络IO,所以很多系统都采用多Web服务器负载均衡,双DB做双机热备(其实就是只有一个DB,两台只...
  • zbuger
  • zbuger
  • 2016-07-12 14:20
  • 1318

sql server中高并发情况下 同时执行select和update语句死锁问题 (一)

最近在项目上线使用过程中使用SqlServer的时候发现在高并发情况下,频繁更新和频繁查询引发死锁。通常我们知道如果两个事务同时对一个表进行插入或修改数据,会发生在请求对表的X锁时,已经被对方持有了。...

sql server中高并发情况下 同时执行select和update语句死锁问题 (二)

SQL Server死锁使我们经常遇到的问题,数据库操作的死锁是不可避免的,本文并不打算讨论死锁如何产生,重点在于解决死锁。希望对您学习SQL Server死锁方面能有所帮助。         ...

不拖控件ASP.NET—探知cookie和session(1)

1.      为什么会出现cookie和session?     Ø  先看一个例子:     我们还是使用之前的NVelocity,不清楚的参看链接:http://blog.c...

mysql的插表以及更新操作导致的死锁问题

一.mysql的死锁: 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。 表级锁不会产生死锁.所以解决死锁主要还是针对于最常用的Inno...

快速理解聚集索引和非聚集索引

数据库的索引,听起来挺神秘的,仔细想想。这些索引,其实就是平时咱们查东西时候常用的两种手段。无非就是为了提高我们找东西的效率而已。那么我们平时又是怎么查东西呢? 聚集索引:       聚集索引,来...

牛顿插值法

插值法利用函数f(x)在某区间中若干点的函数值,作出适当的特定函数,在这些点上取已知值,在区间的其他点上用这特定函数的值作为函数f(x)的近似值。具有唯一性,需要求解各阶差商。如果这特定函数是多项式,...

shell 数组长度

Shell 数组元素个数${#array[@]} 数组的所有元素${array[*]} 字符串长度${#str} 1、获取数组元素的个数:         array=(bill &#...

程序员编程艺术:第三章、寻找最小的k个数

程序员编程艺术:第三章、寻找最小的k个数作者:July。时间:二零一一年四月二十八日。致谢:litaoye, strugglever,yansha,luuillu,Sorehead,及狂想曲创作组。微...

如何解决ajax跨域问题(转)

如何解决ajax跨域问题(转) 由 于此前很少写前端的代码(哈哈,不合格的程序员啊),最近项目中用到json作为系统间交互的手段,自然就伴随着众多ajax请求,随之而来的就是要解...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)