如何解决生产环境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

相关推荐

  • 构建SQL自动审核系统

    Inception Inception是一个开源的Mysql自动化工具,具有SQL审核、执行、回滚等实用的功能,由国内大神基于mysql源码开发,可以很明确的,详细的,准确的审核Mysql的SQL语句,工作模式与Mysql完全相同,可以直接使用mysql客户端来连接。但遗憾的是2年前已停止更新,不过兼容大部分的mysql版本,仍然是开源SQL审核工具的翘楚。…

    2023年1月17日
    1.5K00
  • MySQL 中 DELETE 语句中可以使用别名么?

    某天,正按照业务的要求删除不需要的数据,在执行 DELETE 语句时,竟然出现了报错! 背景 某天,正按照业务的要求删除不需要的数据,在执行 DELETE 语句时,竟然出现了报错(MySQL 数据库版本 5.7.34): 这就有点奇怪了,因为我在执行删除语句之前,执行过同样条件的 SELECT 语句,只是把其中的 select * 换成了…

    2023年11月22日
    1.5K00
  • 数据库慢查询及其优化

    我们经常会谈到数据库慢查询。那么什么是数据库慢查询以及导致数据库慢查询的常见原因,以及对应的解决方法。 1、什么是数据库慢查询 数据库慢查询,就是查询时间超过了我们设定的时间的语句。可以通过语句查看设定的时间: 默认的设定时间是10秒,也可以通过下面这个语句修改默认的设定时间: 2、MySQL 慢查询的相关参数解释 3、慢查询日志配置 默认情况下slow_q…

    2022年6月11日
    1.4K00
  • MySQL服务器开启SSL加密功能

    MySQL服务器开启SSL加密功能 我们知道,MySQL5.7之前版本,安全性做的并不够好,比如安装时生成的root空密码账号、存在任何用户都能连接上的test库等,导致数据库存在较大的安全隐患。好在5.7版本对以上问题进行了一一修复。与此同时,MySQL 5.7版本还提供了更为简单SSL安全访问配置,且默认连接就采用SSL的加密方式,这让数据库的安全性提高…

    2023年12月18日
    1.6K00
  • Mysql备份策略(Linux版)

    1.创建保存备份文件的文件夹 或者挂载一块网络共享硬盘到lunix系统中用于备份,挂载方式: 2.编写脚本 SH脚本内容: 给脚本赋权限 3.制定定时任务 插入这一行,完成定时任务,这里可以设置定时时间:

    2022年8月10日
    1.3K00

发表回复

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

在线咨询: QQ交谈

邮件:712342017@qq.com

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

关注微信