加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

Mysql实例InnoDB数据库死锁问题处理

发布时间:2020-12-12 02:35:16 所属栏目:MySql教程 来源:网络整理
导读:《Mysql实例InnoDB数据库死锁问题处理》要点: 本文介绍了Mysql实例InnoDB数据库死锁问题处理,希望对您有用。如果有疑问,可以联系我们。 场景描述 MYSQL应用 在update表的时候呈现DeadlockLoserDataAccessException异常 (Deadlock found when trying to ge

《Mysql实例InnoDB数据库死锁问题处理》要点:
本文介绍了Mysql实例InnoDB数据库死锁问题处理,希望对您有用。如果有疑问,可以联系我们。

场景描述MYSQL应用

在update表的时候呈现DeadlockLoserDataAccessException异常 (Deadlock found when trying to get lock; try restarting transaction...).MYSQL应用

问题阐发MYSQL应用

这个异常并不会影响用户使用,因为数据库遇到死锁会自动回滚并重试.用户的感觉就是操作稍有卡顿.但是监控老是报异常,所以需要办理一下.MYSQL应用

解决办法MYSQL应用

在应用法式中update的地方使用try-catch.MYSQL应用

我本身封装了一个函数,如下.MYSQL应用

/**
   * 2016-03-15
   * linxuan
   * handle deadlock while update table
   */
  private void updateWithDeadLock(TestMapper mapper,Test record) throws InterruptedException {
    boolean oops;
    int retries = 5;
    do{
      oops = false;
      try{
        mapper.updateByPrimaryKeySelective(record);
      }
      catch (DeadlockLoserDataAccessException dlEx){
        oops = true;
        Thread.sleep((long) (Math.random() * 500));
      }
      finally {
      }
    } while(oops == true && retries-- >0);
  }

我用的是mybatis,所以只需将mapper传进函数,如果不用mybatis,需要本身创建并关闭数据库连接.MYSQL应用

延伸:数据库死锁MYSQL应用

数据库死锁是事务性数据库 (如SQL Server,MySql等)经常遇到的问题.除非数据库死锁问题频繁出现导致用户无法操作,一般情况下数据库死锁问题不严重.在应用程序中进行try-catch就可以.那么数据死锁是如何发生的呢?MYSQL应用

InnoDB实现的是行锁 (row level lock),分为共享锁 (S) 和 互斥锁 (X).MYSQL应用

共享锁用于事务read一行.
互斥锁用于事务update或delete一行.
当客户A持有共享锁S,并哀求互斥锁X;同时客户B持有互斥锁X,并哀求共享锁S.以上情况,会发生数据库死锁.如果还不够清楚,请看下面的例子.MYSQL应用

数据库死锁例子MYSQL应用

首先,客户A创立一个表T,并向T中插入一条数据,客户A开始一个select事务,所以拿着共享锁S.MYSQL应用

mysql> CREATE TABLE t (i INT) ENGINE = InnoDB;
Query OK,0 rows affected (1.07 sec)
mysql> INSERT INTO t (i) VALUES(1);
Query OK,1 row affected (0.09 sec)
mysql> START TRANSACTION;
Query OK,0 rows affected (0.00 sec)
mysql> SELECT * FROM t WHERE i = 1 LOCK IN SHARE MODE;
+------+
| i  |
+------+
|  1 |
+------+

然后,客户B开始一个新事务,新事务是delete表T中的唯一一条数据.MYSQL应用

mysql> START TRANSACTION;
Query OK,0 rows affected (0.00 sec)
mysql> DELETE FROM t WHERE i = 1;

删除操作需要互斥锁 (X),但是互斥锁X和共享锁S是不能相容的.所以删除事务被放到锁哀求队列中,客户B阻塞.MYSQL应用

最后,客户A也想删除表T中的那条数据:MYSQL应用

mysql> DELETE FROM t WHERE i = 1;
ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction

死锁产生了!因为客户A必要锁X来删除行,而客户B拿着锁X并正在等待客户A释放锁S.看看客户A,B的状态:MYSQL应用

客户A: 拿着锁S,期待着客户B释放锁X.
客户B: 拿着锁X,期待着客户A释放锁S.
MYSQL应用

发生死锁后,InnoDB会为对一个客户产生差错信息并释放锁.返回给客户的信息:MYSQL应用

ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction
所以,另一个客户可以正常执行任务.死锁停止.MYSQL应用

欢迎参与《Mysql实例InnoDB数据库死锁问题处理》讨论,分享您的想法,编程之家PHP学院为您提供专业教程。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读