如何解决生产环境MySQL的死锁问题

生产问题

在生产环境中发现我们数据库出现了一个异常,异常堆栈信息如下:

Error updating database. 
Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:
Deadlock found when trying to get lock; try restarting transaction\n### The error may involve
xxxMapper.updateByExampleSelective-Inline\n### The error occurred while setting parameters\n###
SQL: UPDATE xxx  SET to_recipient_id = ?,logistics_order_id = ?,delivery_type = ?,delivery_no = ?,
delivery_company_code = ?,delivery_big_pen = ?,delivery_package_site_name = ?,delivery_extended_attribute = ?,
delivery_label_url = ?,customs_channel_code = ?,declare_no = ?,create_time = ?,update_time = ?,delete_flag = ?,
channel_hawb_code = ?,system_order_code = ?,change_sign = ?,delivery_extended_no = ?,delivery_child_no = ?
WHERE (       (  logistics_order_id = ? ) )

从堆栈信息可以很容易知道死锁问题。但是这个更新语句为什么会出现死锁呢?

问题原因

死锁产生的原因有四个分别是:

  • 互斥
  • 循环等待
  • 不可剥夺
  • 请求与保持

只要产生死锁以上四个条件比然满足,因此考虑这个SQL语句是否产生了这四个死锁条件。

分析:

由于我们使用的是云数据库,因此可以通过云数据库控制台查看锁分析,分析结果如下:

如何解决生产环境MySQL的死锁问题

可以看到死锁的产生是由于两个事务互相竞争导致的,那么两个事务如何产生死锁呢?

两个事务产生死锁的条件如下:

事务1: lock A, then B 事务2: lock B, then A

翻译一下就是:

事务1

update table 1 set name = 1 where id = 1;

update table2 set age = 2 where id = 3;

事务2

update table2 set age = 2 where id = 3;

update table 1 set name = 1 where id = 1;

即两个事务中,T1 锁定了A,要去获取B的资源锁,但是T2已经锁定了资源B,T2要去获取A的锁,两个都不释放,从而导致死锁。

根据这种场景分析生产执行SQL找到了对应的SQL问题,问题的原因也是前面描述的一样,两个事务互相竞争等待导致的。

解决方案

那么针对这种情况如何解决呢?

方案1:两个事务的执行SQL改成一样,即

事务1

update table 1 set name = 1 where id = 1;

update table2 set age = 2 where id = 3;

事务2

update table 1 set name = 1 where id = 1;

update table2 set age = 2 where id = 3;

按照相同的顺序执行SQL,即使出现并发情况,那么行锁也会等待而不会死锁。

方案2:提取事务,将不必要的SQL不加入事务中

事务1

update table 1 set name = 1 where id = 1;

commit;

update table2 set age = 2 where id = 3;

通过分析将不必要的SQL从事务中提取。

文章来源:https://www.cnaaa.net,转载请注明出处:https://www.cnaaa.net/archives/5958

(0)
安屠生的头像安屠生
上一篇 2022年8月21日 下午1:35
下一篇 2022年8月21日 下午1:45

相关推荐

  • mysql内存占用过高的问题

    现象:在mysql运行一天之后,发现内存占用量达到总内存的百分之77,且swap被占用百分之50 问题检查如下: 第一步:开启内存使用的监控服务 第二步: 查看正常实例的使用情况 第三步: 查看内存监控表数据 问题解决:         当事件的内存占用是performance_schema过高的话,可以考虑关闭或者减少该事件使用内存的量,操作如下

    2023年7月26日
    1.2K00
  • Oracle用户密码过期的处理方法

    受影响版本:Oracle11g以上版本。 导致密码消失的原因:Oracle 11g中默认的DEFAULT概要文件中口令有效期PASSWORD_LIFE_TIME默认值为180天。 当以客户端登陆Oracle提示ORA-28002,则基本可以确定登陆帐号已过有效期,使用具有DBA权限的帐号重置该帐号密码即可。 解决方法: 以下步骤以具有DBA权限用户操作 1.…

    2024年5月9日
    1.3K00
  • Redis 常用命令

    一、redis启动: Redis 连接命令 二、redis keys命令 三、reids字符串命令 四、Redis hash 命令 五、Redis 列表命令 六、Redis 集合命令 七、Redis 有序集合命令 八、Redis 发布订阅命令 九、Redis 事务命令 十、Redis 脚本命令 十一、Redis 服务器命令

    2022年7月29日
    1.2K00
  • Redis 缓存雪崩、缓存穿透、缓存击穿、缓存预热

    缓存雪崩 定义 缓存雪崩是指在短时间内,有大量缓存同时过期,导致大量的请求直接查询数据库,从而对数据库造成了巨大的压力,严重情况下可能会导致数据库宕机的情况叫做缓存雪崩。 正常情况下执行过程: 缓存雪崩下执行过程: 可以看到,当缓存失效时,大量请求直接绕过 Redis 去请求数据库,导致会对数据库造成很大压力。 解决 加锁排队 加锁排队可以起到缓冲的作用,防…

    2022年11月17日
    1.2K00
  • MySQL 用户管理和权限管理

    在项目中,一个数据库有很多人需要使用,不能所有的人都使用相同的权限,如果人比较多,一人一个用户也很难管理。一般来说,会分超级管理员权限,管理员权限,读写权限,只读权限等,这样方便管理。当然,具体怎么管理权限根据实际情况来确定。无论如何,都需要创建多个用户来管理权限。root 是数据库的超级管理员用户,对于普通开发人员来说,权限太大了,如果不小心做了一些不可逆…

    2022年6月9日
    1.6K00

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

在线咨询: QQ交谈

邮件:712342017@qq.com

工作时间:周一至周五,8:30-17:30,节假日休息

关注微信