InnoDB数据库死锁问题处理
作者:hebedich 发布时间:2024-01-19 13:30:59
场景描述
在update表的时候出现DeadlockLoserDataAccessException异常 (Deadlock found when trying to get lock; try restarting transaction...)。
问题分析
这个异常并不会影响用户使用,因为数据库遇到死锁会自动回滚并重试。用户的感觉就是操作稍有卡顿。但是监控老是报异常,所以需要解决一下。
解决方法
在应用程序中update的地方使用try-catch。
我自己封装了一个函数,如下。
/**
* 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。
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> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> DELETE FROM t WHERE i = 1;
删除操作需要互斥锁 (X),但是互斥锁X和共享锁S是不能相容的。所以删除事务被放到锁请求队列中,客户B阻塞。
最后,客户A也想删除表T中的那条数据:
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
所以,另一个客户可以正常执行任务。死锁结束。


猜你喜欢
- 前言加密技术在数据安全存储,数据传输中发挥着重要作用,能够保护用户隐私数据安全,防止信息窃取。RSA是一种非对称加密技术,在软件、网页中已得
- 本文实例讲述了Python3使用turtle绘制超立方体图形。分享给大家供大家参考,具体如下:利用Python3中turtle的绘制超立方体
- 程序员的浪漫,你懂吗?今天使用python小海龟实现爱心图案的绘制,代码如下:import turtleimport time# 清屏函数d
- 1 前言很多程序都要求用户输入某种信息,程序一般将信息存储在列表和字典等数据结构中。用户关闭程序时,就需要将信息进行保存,一种简单的方式是使
- 工厂模式(Factory Pattern)是什么工厂模式是一种创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会
- 一、isdigit()函数isdigit()函数是检测输入字符串是否只由数字组成。如果字符串只包含数字则返回 True 否则返回 False
- 很喜欢Python这门语言。在看过语法后学习了Django 这个 Web 开发框架。算是对 Python 有些熟悉了。不过对里面很多东西还是
- 由于文件夹可能有多层目录,因此需要对其进行递归遍历。本文采取了简单的协议定制,定义了五条命令,指令Head如下:Sync:标识开始同步文件夹
- Python是一门简单易学的编程语言。阅读好的Python程序感觉就像阅读英语,尽管是非常严格的英语。Python的这种伪代码特性是其最大强
- 简单介绍HTTP是超文本传输协议,其定义了客户端与服务器端之间文本传输的规范。HTTP默认使用80端口,这个端口指的是服务端的端口,而客户端
- 一,json.load()和json.dump只要用于读写json数据1json.load()从文件中读取json字符串with open(
- asp网站程序在国内运用很广,但是类似于im286.asp?id=20050307213811这样的url有点不利于搜索引擎的收录,也就是说
- 前言深度学习框架在市面上有很多。比如Theano、Caffe、CNTK、MXnet 、Tensorflow等。今天讲解的就是主角Tensor
- 1. __init__ 初始化文件路径,关键字1,关键字2;2. key_match 使用with open 方法,以二进制方式(也可以改成
- 一、MySQL中的日期时间类型MySQL中常用的几种时间类型有:date、datetime、time、year、timestampdatet
- 本文实例讲述了Python实现的视频播放器功能。分享给大家供大家参考,具体如下:# -*- coding:utf-8 -*-#! pytho
- 记得导入包,其他按键可类比def keyPressEvent(self, event): if event.key() == Q
- 按照下面一步一步来,安 * p就是这么简单。脚本之家下载渗透测试软件Burp Suite Professionalhttps://www.jb
- 【代码示例】 [code=SQL] DELIMITER $$ DROP FU
- new Array() new Array(len) new Array([item0,[item1,[item2,...]]] 使用数组对