gpt4 book ai didi

InnoDB数据库死锁问题处理

转载 作者:qq735679552 更新时间:2022-09-29 22:32:09 24 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章InnoDB数据库死锁问题处理由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

场景描述 。

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

问题分析 。

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

解决方法 。

在应用程序中update的地方使用try-catch.

我自己封装了一个函数,如下.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
    * 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,需要自己创建并关闭数据库连接.

延伸:数据库死锁 。

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

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

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

数据库死锁例子 。

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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中的唯一一条数据.

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

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

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

?
1
2
3
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的状态:

客户A: 拿着锁S,等待着客户B释放锁X。 客户B: 拿着锁X,等待着客户A释放锁S.

发生死锁后,InnoDB会为对一个客户产生错误信息并释放锁。返回给客户的信息:

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

最后此篇关于InnoDB数据库死锁问题处理的文章就讲到这里了,如果你想了解更多关于InnoDB数据库死锁问题处理的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com