精华内容
下载资源
问答
  • 可参考: 数据库死锁那些事儿 https://blog.csdn.net/eseaqyq/article/details/7795023 MySQL InnoDB死锁死锁检测(四)http://www.ywnds.com/?p=4949 二、MySQL InnoDB死锁检测 1) 尽量不出现死锁 在代码层...

    可参考: 数据库中死锁那些事儿 https://blog.csdn.net/eseaqyq/article/details/7795023
    MySQL InnoDB死锁及死锁检测(四)http://www.ywnds.com/?p=4949

    二、MySQL InnoDB死锁检测
    1) 尽量不出现死锁

    在代码层调整SQL操作顺序,或者缩短事务长度,以避免出现死锁。

    2) 碰撞检测

    当死锁出现时,Innodb会主动探知到死锁,并回滚了某一苦苦等待的事务。问题来了,Innodb是怎么探知死锁的?

    核心就是数据库会把事务单元锁维持的锁和它所等待的锁都记录下来,Innodb提供了wait-for graph算法来主动进行死锁检测,每当加锁请求无法立即满足需要进入等待时,wait-for graph算法都会被触发。当数据库检测到两个事务不同方向地给同一个资源加锁(产生循序),它就认为发生了死锁,触发wait-for graph算法。比如,事务1给A加锁,事务2给B加锁,同时事务1给B加锁(等待),事务2给A加锁就发生了死锁。那么死锁解决办法就是终止一边事务的执行即可,这种效率一般来说是最高的,也是主流数据库采用的办法。

    Innodb目前处理死锁的方法就是将持有最少行级排他锁的事务进行回滚。这也是相对比较简单的死锁回滚方式。死锁发生以后,只有部分或者完全回滚其中一个事务,才能打破死锁。对于事务型的系统,这是无法避免的,所以应用程序在设计必须考虑如何处理死锁。大多数情况下只需要重新执行因死锁回滚的事务即可。

    wait-for graph原理

    我们怎么知道图中四辆车是死锁的?

    MySQL InnoDB死锁及死锁检测(四)

    他们相互等待对方的资源,而且形成环路!我们将每辆车看为一个节点,当节点1需要等待节点2的资源时,就生成一条有向边指向节点2,最后形成一个有向图。我们只要检测这个有向图是否出现环路即可,出现环路就是死锁!这就是wait-for graph算法。

    MySQL InnoDB死锁及死锁检测(四)

    Innodb将各个事务看为一个个节点,资源就是各个事务占用的锁,当事务1需要等待事务2的锁时,就生成一条有向边从1指向2,最后行成一个有向图。

    3)等锁超时

    死锁超时也是一种常见的做法,就是等待锁持有时间,如果说一个事务持有锁超过设置时间的话,就直接抛出一个错误,参数innodb_lock_wait_timeout用来设置超时时间。如果有些用户使用哪种超长的事务,你就需要把锁超时时间大于事务执行时间。在这种情况下这种死锁超时的方式就会导致每一个死锁超时被发现的时间是无法接受的。

    不要太担心死锁,你可能会在MySQL error log中看到关于死锁的警告信息,或者在show engine InnoDB status输出中看到它。尽管看起来是一个可怕的名字,但deadlock不是一个严重的问题,对于InnoDB来说,通常不需要做任何纠正操作。当两个事务开始修改多个表时,如果访问表的顺序不同,会出现互相等待对方释放锁,然后才能继续处理的情况。MySQL会立刻发现这种情况并且终止较小的事务,允许其他的事务执行。

    你的应用程序的确需要错误处理逻辑来重启该事务。当你重新执行相同的SQL语句时,原来的时间问题不再适用:要么其他的事务已经执行完成,这样你就可以执行事务了,要么其他的事务还在处理过程中,你的事务只能等它结束。

    如果不断警告发生死锁,你可能要review你的应用程序源代码,调整SQL操作顺序,或者缩短事务长度。你可以启用innodb_print_all_deadlocks选项,把deadlock信息记录到MySQL的错误日志总,而不是仅仅通过show engine innob status查看。

    锁跟索引的关系

    这时我们要注意到,money表虽然没有添加索引,但是InnoDB存储引擎会使用隐式的主键来进行锁定。对于没有索引或主键的表来说,那么MySQL会给整张表的所有数据行的加行锁。这里听起来有点不可思议,但是当sql运行的过程中,MySQL并不知道哪些数据行是id=1(没有索引嘛),如果一个条件无法通过索引快速过滤,存储引擎层面就会将所有记录加锁后返回,再由MySQL Server层进行过滤。但在实际使用过程当中,MySQL做了一些改进,在MySQL Server过滤条件,发现不满足后,会调用unlock_row方法,把不满足条件的记录释放锁 (违背了二段锁协议的约束)。这样做,保证了最后只会持有满足条件记录上的锁,但是每条记录的加锁操作还是不能省略的。可见即使是MySQL,为了效率也是会违反规范的。这种情况同样适用于MySQL的默认隔离级别RC。所以对一个数据量很大的表做批量修改的时候,如果无法使用相应的索引,MySQL过滤数据的的时候特别慢,就会出现虽然没有修改某些行的数据,但是它们还是被锁住了的现象。

    展开全文
  • 什么是数据库死锁? 两个或以上事务同时对一批资源占用锁,并形成循环,就会造成事务死锁,一般报错如下: ... try restarting transaction 1 插入场景:(user_id和pool_id是联合唯一索引) ...
    什么是数据库死锁?
    两个或以上事务同时对一批资源占用锁,并形成循环,就会造成事务死锁,一般报错如下:
    com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
    1 插入场景:(user_id和pool_id是联合唯一索引)
    场景:有一个job,定时会查出一批数据,然后分页,每页一千条数据批量插入数据库中,伪代码如下:
    ---------------------
    int totalRow = xxxMapper.count();
    for (int page=0; page <= totalRow/pageSize; page++) {
        List<Xxx> data = xxxMapper.selectByPage(page * pageSize, pageSize);  // 这里分页可用上一次的最大id,用偏移量只是方便理解
        if (CollectionUtils.isNotEmpty(data)) xxxMapper.batchInsert(data);
    }
    ---------------------
    上面没有开一个统一的事务,所以每次batchInsert()都是一次独立新的事务,多次独立事务批量插入,并且user_id和pool_id是联合唯一索引当时就发现如下问题:
    ### Error updating database.  Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
    ### SQL: insert into leads_distribution_pool ( user_id, pool_id ) values ( ?,         ? ) ,  ( ?,         ? );
     
    - 产生原因分析(IK等待NK,而不同事务之间的NK又会相互等待RK导致的
    在分批插入中,事务A会先申请对应行记录(假设是1,2,3)的行锁X RK(排他 行级锁),然后事务B也会申请对应行记录(假设是4,5,6)X RK. 这时候事务A他需要插入,会先申请一个X IK(排他 插入意向锁),因为X IK是需要获取S NK锁(共享 next-key锁),但是由于事务B对4,5,6加了X RK,所以事务A的next-key锁里面的间隙锁无法对1,2,3周围的间隙如4加一个锁,这时候事务A就获取S NK锁失败,导致无法获取X IK锁,同理事务B也是这种,由于事务A的X NK阻塞,导致获取插入意向锁也失败,这样就会形成一种相互等待的状态,从而导致死锁。
    - 解决方案:
    -- 第一种:给批量插入加一个redis锁,处理完一个在处理下一个批量插入
    -- 第二种:降低隔离级别,比如把隔离级别变为可提交读(Innodb中S NK和X IK是Innodb可重复度级别才有)
     
    2 更新场景:(teacher_oa_id是普通索引,id是主键索引)
    - 原来的SQL:update user set hujin_wx_id = 121 WHERE teacher_oa_id = #{oaId}
    - 改造后的SQL:update user set hujin_wx_id = 121 WHERE id = #{id}
    区别就是原来的用了两个索引,而innodb中的行级锁是锁索引的,先会锁住非主键索引,再根据非主键索引找到主键索引,然后把主键索引锁住。
    问题就在这里,假设有另一个sql是:update user set teacher_oa_id = #{oaId}  WHERE id = #{id},这样就先锁住主键索引,然后更新teacher_oa_id需要获取这个非主键索引的行级锁,然后这时候由于另一条sql已经锁住teacher_oa_id索引了,这时候这条sql想去锁teacher_oa_id索引就失败了。然后原来的sql等待id主键索引的锁,另一个sql等待teacher_oa_id的索引.解决办法:将oaId改成用id来查找,这样直接找主键索引就不会死锁冲突。
    展开全文
  • 数据库死锁原因及解决办法(全)

    万次阅读 多人点赞 2019-02-28 10:03:59
    死锁(Deadlock) 所谓死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的...

    死锁(Deadlock)

    所谓死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。由于资源占用是互斥的,当某个进程提出申请资源后,使得有关进程在无外力协助下,永远分配不到必需的资源而无法继续运行,这就产生了一种特殊现象死锁。 一种情形,此时执行程序中两个或多个线程发生永久堵塞(等待),每个线程都在等待被其他线程占用并堵塞了的资源。例如,如果线程A锁住了记录1并等待记录2,而线程B锁住了记录2并等待记录1,这样两个线程就发生了死锁现象。计算机系统中,如果系统的资源分配策略不当,更常见的可能是程序员写的程序有错误等,则会导致进程因竞争资源不当而产生死锁的现象。锁有多种实现方式,比如意向锁,共享-排他锁,锁表,树形协议,时间戳协议等等。锁还有多种粒度,比如可以在表上加锁,也可以在记录上加锁。 


    产生死锁的原因主要是:

    (1)系统资源不足。

    (2) 进程运行推进的顺序不合适。

    (3)资源分配不当等。

    如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。


    产生死锁的四个必要条件:

    (1) 互斥条件:一个资源每次只能被一个进程使用。
    (2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
    (3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
    (4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

      这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。


    死锁的预防和解除:

    理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和解除死锁。所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止进程在处于等待状态的情况下占用资源,在系统运行过程中,对进程发出的每一个系统能够满足的资源申请进行动态检查,并根据检查结果决定是否分配资源,若分配后系统可能发生死锁,则不予分配,否则予以分配 。因此,对资源的分配要给予合理的规划。
     


    如何将死锁减至最少

    虽然不能完全避免死锁,但可以使死锁的数量减至最少。将死锁减至最少可以增加事务的吞吐量并减少系统开销,因为只有很少的事务回滚,而回滚会取消事务执行的所有工作。由于死锁时回滚而由应用程序重新提交。

    下列方法有助于最大限度地降低死锁:

    (1)按同一顺序访问对象。

    (2)避免事务中的用户交互。

    (3)保持事务简短并在一个批处理中。

    (4)使用低隔离级别。

    (5)使用绑定连接。

    1、按同一顺序访问对象

    如果所有并发事务按同一顺序访问对象,则发生死锁的可能性会降低。例如,如果两个并发事务获得 Supplier 表上的锁,然后获得 Part 表上的锁,则在其中一个事务完成之前,另一个事务被阻塞在 Supplier 表上。第一个事务提交或回滚后,第二个事务继续进行。不发生死锁。将存储过程用于所有的数据修改可以标准化访问对象的顺序。

    2、避免事务中的用户交互

    避免编写包含用户交互的事务,因为运行没有用户交互的批处理的速度要远远快于用户手动响应查询的速度,例如答复应用程序请求参数的提示。例如,如果事务正在等待用户输入,而用户去吃午餐了或者甚至回家过周末了,则用户将此事务挂起使之不能完成。这样将降低系统的吞吐量,因为事务持有的任何锁只有在事务提交或回滚时才会释放。即使不出现死锁的情况,访问同一资源的其它事务也会被阻塞,等待该事务完成。

    3、保持事务简短并在一个批处理中

    在同一数据库中并发执行多个需要长时间运行的事务时通常发生死锁。事务运行时间越长,其持有排它锁或更新锁的时间也就越长,从而堵塞了其它活动并可能导致死锁。

    保持事务在一个批处理中,可以最小化事务的网络通信往返量,减少完成事务可能的延迟并释放锁。

    4、使用低隔离级别

    确定事务是否能在更低的隔离级别上运行。执行提交读允许事务读取另一个事务已读取(未修改)的数据,而不必等待第一个事务完成。使用较低的隔离级别(例如提交读)而不使用较高的隔离级别(例如可串行读)可以缩短持有共享锁的时间,从而降低了锁定争夺。

    5、使用绑定连接

    使用绑定连接使同一应用程序所打开的两个或多个连接可以相互合作。次级连接所获得的任何锁可以象由主连接获得的锁那样持有,反之亦然,因此不会相互阻塞。

    6、用存储过程查出引起死锁的进程和SQL语句

    假如发生了死锁,我们怎么去检测具体发生死锁的是哪条SQL语句或存储过程?此时我们可以使用以下存储过程来检测,就可以查出引起死锁的进程和SQL语句。


     

    与锁定有关的两个问题--死锁和阻塞

     

    死锁

    死锁是一种条件,不仅仅是在关系数据库管理系统 (RDBMS) 中发生,在任何多用户系统中都可以发生的。当两个用户(或会话)具有不同对象的锁,并且每个用户需要另一个对象的锁时,就会出现死锁。每个用户都等待另一个用户释放他的锁。当两个连接陷入死锁时,Microsoft® SQL Server? 会进行检测。其中一个连接被选作死锁牺牲品。该连接的事务回滚,同时应用程序收到错误。

    如果死锁变成单个公用事件,而且它们的回滚造成过多的性能降级,那么就需要再次进行深入彻底的调查。使用跟踪标记 1204。例如,下面的命令从命令提示符启动 SQL Server,并启用跟踪标记 1204:

    c:\mssql\binn\sqlservr -T1204

    现在所有消息都会显示在启动 SQL Server 的控制台屏幕上和错误日志中。

    使用分布式事务时,也可能发生死锁。


    阻塞

    任何基于锁的并发系统都不可避免地具有可能在某些情况下发生阻塞的特征。当一个连接控制了一个锁,而另一个连接需要冲突的锁类型时,将发生阻塞。其结果是强制第二个连接等待,或在第一个连接上阻塞。

    在本主题中,术语"连接"是指数据库的单个登录会话。每个连接都作为系统进程 ID (SPID) 出现。尽管每一个 SPID 一般都不是单独的进程上下文,但这里常常用来指一个进程。更确切的说,每个 SPID 都是由服务器资源和数据结构(为给定客户单个连接的请求提供服务)组成。单个客户应用程序可能有一个或多个连接。就 SQL Server 而言,从单个客户机上的单个客户应用程序来的多个连接和从多个客户应用程序或多个客户机来的多个连接是没有区别的。不管是来自同一应用程序还是来自两台不同客户机上单独的应用程序,一个连接都可以阻塞另一个连接。

    展开全文
  • 数据库死锁

    千次阅读 2016-07-07 15:38:13
    最近做项目时,将原先单条插入更新数据库时改为批量插入更新。这样做的好处是降低了QPS(sql语句的数量),但是同时也带来一个问题,DB的行锁急剧增加。 由于批量更新执行时间长,导致资源被长时间锁定,从而导致了...
    最近做项目时,将原先单条插入更新数据库时改为批量插入更新。这样做的好处是降低了QPS(sql语句的数量),但是同时也带来一个问题,DB的行锁急剧增加。
    由于批量更新执行时间长,导致资源被长时间锁定,从而导致了大量的死锁产生,即出现以下错误信息:
    Deadlock found when trying to get lock; try restarting transaction
    借这个机会,研究一下数据库死锁的问题。
     
    一. 什么是数据库死锁?
    学过操作系统的人都知道,只有在并发的情况下,才会发生死锁。
    下面的图可以形象地说明死锁的形成,四辆车在一个环形车道上行驶,如果没有外力作用,这4辆车将无法运行。
    死锁发生在当多个进程访问同一数据库时,其中每个进程拥有的锁都是其他进程所需的,由此造成每个进程都无法继续下去。
    简单的说,进程A等待进程B释放他的资源,B又等待A释放他的资源,这样就互相等待就形成死锁。
    产生死锁的四个必要条件是:
    1)互斥条件: 指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。
    2)请求和保持条件: 指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
    3)不剥夺条件: 指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
    4)环路等待条件: 指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。
    这四个条件缺一不可。
     
    二. 数据库死锁检测
    我们mysql用的存储引擎是innodb,从打印的错误日志来看,innodb主动探知到死锁,并回滚了某一苦苦等待的事务。那么innodb是怎么探知死锁的?
    直观方法是在两个事务相互等待时,当一个等待时间超过设置的某一阀值时,对其中一个事务进行回滚,另一个事务就能继续执行。这种方法简单有效,在innodb中,参数innodb_lock_wait_timeout用来设置超时时间。
    仅用上述方法来检测死锁太过被动,innodb还提供了wait-for graph算法来主动进行死锁检测,每当加锁请求无法立即满足需要并进入等待时,wait-for graph算法都会被触发。
     我们怎么知道上图中四辆车是死锁的?他们相互等待对方的资源,而且形成环路!我们将每辆车看为一个节点,当节点1需要等待节点2的资源时,就生成一条有向边指向节点2,最后形成一个有向图。 我们只要检测这个有向图是否出现环路即可,出现环路就是死锁!这就是wait-for graph算法。
      innodb将各个事务看为一个个节点,资源就是各个事务占用的锁,当事务1需要等待事务2的锁时,就生成一条有向边从1指向2,最后行成一个有向图。
     
    三.InnoDB锁原理
    我们知道,innodb最大的贡献就是支持了事务和行锁,由于锁的粒度更细,所以能更好的支持并发。
    InnoDB实现了以下两种类型的行锁:
    共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
    排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。
    另外,为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁。
    意向锁是InnoDB自动加的,不需用户干预。这里不做过多分析。
    对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及的数据集加排他锁(X);
    对于普通SELECT语句,InnoDB不会加任何锁
    但是select语句可以显式的加共享锁和排他锁。
    ·共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE。
    ·排他锁(X):SELECT * FROM table_name WHERE ... FOR UPDATE。
    用SELECT ... IN SHARE MODE获得共享锁,主要用在需要数据依存关系时来确认某行记录是否存在,并确保没有人对这个记录进行UPDATE或者DELETE操作。
    但是如果当前事务也需要对该记录进行更新操作,则很有可能造成死锁,对于锁定行记录后需要进行更新操作的应用,应该使用SELECT... FOR UPDATE方式获得排他锁。
     
    在5.5中,information_schema 库中增加了三个关于锁的表:
    innodb_trx         ## 当前运行的所有事务
    innodb_locks       ## 当前出现的锁
    innodb_lock_waits  ## 锁等待的对应关系
    innodb_locks记录了当前的锁的信息,其表的结构依次如下:
    a) lock_id:锁的id以及被锁住的空间id编号、页数量、行数量
    b) lock_trx_id:锁的事务id。
    c) lock_mode:锁的模式。
    d) lock_type:锁的类型,表锁还是行锁
    e) lock_table:要加锁的表。
    f) lock_index:锁的索引。
    g) lock_space:innodb存储引擎表空间的id号码
    h) lock_page:被锁住的页的数量,如果是表锁,则为null值。
    i) lock_rec:被锁住的行的数量,如果表锁,则为null值。
    j) lock_data:被锁住的行的主键值,如果表锁,则为null值。
    锁与索引的关系
    假设我们有一张消息表(msg),里面有3个字段。假设id是主键,token是非唯一索引,message没有索引。
    CREATE TABLE msg (
    id int,
    token int,
    message varchar(100),
    primary key(id),
    index(token)
    )
    innodb对于主键使用了聚簇索引,这是一种数据存储方式,表数据是和主键一起存储,主键索引的叶结点存储行数据。
    对于普通索引,其叶子节点存储的是主键值。
    插入几条数据:
    insert into msg values (1,20,'abc1');
    insert into msg values (2,21,'abc2');
    insert into msg values (3,22,'abc3');
    insert into msg values (4,23,'abc4');
    insert into msg values (5,21,'abc2');
    聚簇索引的存储结构如下所示:
    idtokenmessage
    120abc1
    221abc2
    322abc3
    423abc4
    521abc2
    因为token是普通索引,即二级索引,其存储结构如下,节点是主键值:
    tokenid
    201
    212
    215
    223
    234
     
    下面分析下索引和锁的关系。
    1.delete from msg where id=2;
     由于id是主键,因此直接锁住整行记录即可,会对该行加X锁。
    2. delete from msg where token=21;
    由于token是二级索引,因此首先锁住二级索引(两行),接着会锁住相应主键所对应的记录;
     
    3. delete from msg where message='abc1';
     message没有索引,所以走的是全表扫描过滤。这时表上的各个记录都将添加上X锁。
    从上面的分析可以得出结论:
    innodb的行级锁并不是直接锁记录,而是锁索引;
    如果一条SQL语句用到了主键索引,mysql会锁住主键索引;
    如果一条语句操作了非主键索引,mysql会先锁住非主键索引,再锁定主键索引。
     
    四. 死锁成因
     了解了innodb锁的基本原理后,下面分析下死锁的成因。如前面所说, 死锁一般是事务相互等待对方资源,最后形成环路造成的。下面简单讲下造成相互等待最后形成环路的例子。
    一般情况只发生锁超时,就是一个进程需要访问数据库表或者字段的时候,另外一个程序正在执行带锁的访问(比如修改数据),那么这个进程就会等待,当等了很久锁还没有解除的话就会锁超时,报告一个系统错误,拒绝执行相应的SQL操作。
    发生死锁的情况比较少,比如一个进程需要访问两个资源(数据库表或者字段),当获取一个资源的时候进程就对它执行锁定,然后等待下一个资源空闲,这时候如果另外一个进程也需要两个资源,而已经获得并锁定了第二个资源,那么就会死锁,因为当前进程锁定第一个资源等待第二个资源,而另外一个进程锁定了第二个资源等待第一个资源,两个进程都永远得不到满足。
    在本次项目中造成死锁的原因: 相同表记录行锁冲突
     
    这种情况比较常见,两个事务在执行数据批量更新时,事务A处理的的id列表为[1,2],而事务B处理的id列表为[2,1]。
    事务A执行id=1的更新,id=1行锁被锁定;同时事务B更新id=2,id=2行锁也被锁定。
    这样事务1为了执行id=2的更新,必要要等待id=2的行锁释放;但是事务2还未结束,行锁还未被释放,所以就无法继续执行。
    同样,事务2也无法执行id=1的更新。最终形成了如下图所示的环路等待:

    两个事务在相互等待对方释放资源,这样就造成了死锁。

    A和B在互相等待对方资源的过程中,形成了死锁。
     
    五. 如何尽可能避免死锁
    1)以固定的顺序访问表和行。比如对两个job批量更新的情形,简单方法是对id列表先排序,后执行,这样就避免了交叉等待锁的情形;将两个事务的sql顺序调整为一致,也能避免死锁。
    2)大事务拆小。大事务更倾向于死锁,如果业务允许,将大事务拆小。
    3)在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁概率。
    4)降低隔离级别。如果业务允许,将隔离级别调低也是较好的选择, 执行提交读允许事务读取另一个事务已读取(未修改)的数据,而不必等待第一个事务完成。使用较低的隔离级别(例如提交读)而不使用较高的隔离级别(例如可串行读)可以缩短持有锁的时间,从而降低了锁定争夺。
    5)为表添加合理的索引。可以看到如果不走索引将会为表的每一行记录添加上锁,死锁的概率大大增大。
     
     
    展开全文
  • 线上某服务时不时报出如下异常(大约一天二十多次):“Deadlock found when trying to get lock;”。       Oh, My God! 是死锁问题。...为了更系统的分析问题,本文将从死锁检测、索引隔离...
  • 数据库常见死锁原因及处理

    万次阅读 2018-11-16 11:27:02
    死锁(Deadlock)   所谓死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相...
  • 数据库】mysql死锁问题分析

    千次阅读 2020-04-07 15:09:53
    线上某服务时不时报出如下异常(大约一天二十多次):“Deadlock found when trying to get ... 为了更系统的分析问题,本文将从死锁检测、索引隔离级别与锁的关系、死锁成因、问题定位这五个方面来展开讨论。 ...
  • 数据库死锁原因及解决办法

    万次阅读 2016-11-07 16:31:24
    死锁(Deadlock)   所谓死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在...
  • 数据库死锁及解决死锁问题

    千次阅读 2015-11-14 10:04:30
    所谓死锁: 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程.由于...
  • 数据库事务(死锁)

    2020-09-22 02:19:58
    死锁!!!!!! 最近面试被问的比较多的就是死锁。。(记录一下吧 什么情况下会出现死锁 项目中什么时候会出现死锁 死锁跟事务的联系? 死锁产生的条件 有哪些锁? 死锁会造成什么问题? Mysql如何保持原子性,...
  • [color=red]什么是数据库死锁 每个使用关系型数据库的程序都可能遇到数据死锁的情况。理解什么是死锁之前先要了解锁定的概念:如果需要“修改”一条数据,首先数据库管理系统会在上面加锁,以保证在同一时间只有...
  •  线上生产环境在某些时候经常性的出现数据库操作死锁,导致业务人员无法进行操作。经过DBA的分析,是某一张表的insert操作和delete操作发生了死锁。简单介绍下数据库的情况(因为涉及到真实数据,这里做了模拟,不...
  • 最近在看一些东西sharding-jdbc,突然想写一下数据库死锁相关的问题。好像前者后者没什么必要关系哈。 关于数据库发生死锁可能很少人遇到过,也可能遇到了看到一个报错你就过去了(因Mysql有检测死锁机制),没当回...
  • 数据库并发控制之活锁和死锁

    千次阅读 2018-10-22 16:17:58
    这样就出现了T1在等待T2,而T2又在等待T1的局面,T1和T2两个事务永远不能结束,形成死锁。如图所示: 死锁的解决方法有: 1、死锁的预防 采取一定措施来预防死锁的发生。在数据库中,产生死锁的原因是两个或...
  • 数据库线程死锁

    2017-05-08 11:07:25
     线上生产环境在某些时候经常性的出现数据库操作死锁,导致业务人员无法进行操作。经过DBA的分析,是某一张表的insert操作和delete操作发生了死锁。简单介绍下数据库的情况(因为涉及到真实数据,这里做了模拟,不...
  • 分布式数据库系统中的死锁处理
  • 如果需要“修改”一条数据,首先数据库管理系统会在上面加锁,以保证在同一时间只有一个事务能进行修改操作。锁定(Locking)发生在当一个事务获得对某一资源的“锁”时,这时,其他的事务就不能更改这个资源了,这种...
  • 死锁概览: Java语言通过synchronized关键字来保证原子性,这是因为每一个Object都有一个隐含的锁,这个也称作监视器对象,在进入synchronized之前自动自动获取此内部锁,而一旦离开此方式,无论是完成还是中断都会自动...
  • 数据库索引 锁 死锁

    2020-08-26 11:31:28
    死锁 多个进程在运行过程中因争夺资源而造成的一种僵局 a b线程互相获得对方需要的锁 你等我 我等你 互斥条件:一个资源每次只能被一个进程使用。 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持...
  • 数据库死锁 和 阻塞

    千次阅读 2012-09-22 18:57:45
    数据库死锁原因及解决办法 死锁(Deadlock) 所谓死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。 此时称系统处于死锁状态或...
  • 这篇文章主要介绍了mysql数据库锁的产生原因及解决办法,需要的朋友可以参考下 数据库和操作系统一样,是一个多用户使用的共享资源。当多个用户并发地存取数据 时,在数据库中就会产生多个事务同时存取同一数据的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 22,365
精华内容 8,946
关键字:

数据库死锁是如何形成