在分析案例之前,我们先了解一下MySQL INNODB。在MySQL INNODB引擎中主键是采用聚簇索引的形式,即在B树的叶子节点中既存储了索引值也存储了数据记录,即数据记录和主键索引是存在一起的。而普通索引的叶子节点存储的只是主键索引的值,一次查询找到普通索引的叶子节点后,还要根据叶子节点中的主键索引去找到聚簇索引叶子节点并拿到其中的具体数据记录,这个过程也叫“回表”。

故障发生的场景是关于我们商城的订单系统。有一个定时任务,每一小时跑一次,每次把所有一小时前未支付订单取消掉。而客服后台也可以批量取消订单。订单表 t_order结构大至如下:

id

订单id,主键

status

订单状态

created_time

订单创建时间

id是表的主键,created_time字段上是普通索引。

聚簇索引(主键id)

id(索引)

status

created_time

1

UNPAID

2020-01-01 07:30:00

2

UNPAID

2020-01-01 08:33:00

3

UNPAID

2020-01-01 09:30:00

4

UNPAID

2020-01-01 09:39:00

5

UNPAID

2020-01-01 09:50:00

普通索引(created_time字段)

created_time(索引)

id(主键)

2020-01-01 09:50:00

5

2020-01-01 09:39:00

4

2020-01-01 09:30:00

3

2020-01-01 08:33:00

2

2020-01-01 07:30:00

1

定时任务每一小时跑一次,每次把所有一小时前两小时内的未支付订单取消掉,比如上午11点会取消8点到10点的未支付订单。SQL语句如下:

update t_order set status = 'CANCELLED' where created_time > '2020-01-01 08:00:00' and created_time < '2020-01-01 10:00:00' and status = 'UNPAID'

客服批量取消订单SQL如下:

update t_order set status = 'CANCELLED' where id in (2, 3, 5) and status = 'UNPAID'

上面的两条语句同时执行就可能发生死锁。我们来分析一下原因。第一条定时任务的SQL,会先找到 created_time普通索引并加锁,然后再在找到主键索引并加锁。
第一步,created_time普通索引加锁

第二步,主键索引加锁

第二条客服批量取消订单SQL,直接走主键索引,直接在主键索引上加锁。

我们可以看到,定时任务 SQL对主键加锁顺序是5,4,3,2。客服批量取消订单 SQL对主键加锁顺序是2,3,5。当第一个 SQL对3加锁后,正准备对2加锁时,发现2已经被第二个SQL加锁了,所以第一个SQL要等待2的锁释放。而此时第二个SQL准备对3加锁,却发现3已经被第一个SQL加锁了,就要等待3的锁释放。两个SQL互相等待对方的锁,也就发生了“死锁”。

解决办法就是从SQL语句上保证加锁顺序一致。或者把客服批量取消订单 SQL改成每次 SQL操作只能取消一个订单,然后在程序里多次循环执行SQL,如果批量操作的订单数量不多,这种笨办法也是可行的。

MySQL 数据库死锁问题的更多相关文章

  1. mysql数据库死锁的产生原因及解决办法

    这篇文章主要介绍了mysql数据库锁的产生原因及解决办法,需要的朋友可以参考下   数据库和操作系统一样,是一个多用户使用的共享资源.当多个用户并发地存取数据 时,在数据库中就会产生多个事务同时存取同 ...

  2. MySQL 数据库死锁

    数据库死锁 死锁的解决办法(1) 执行下面SQL,先查看哪些表被锁住了: select b.owner,b.object_name,a.session_id,a.locked_mode from v$ ...

  3. MySQL数据库死锁分析

    背景说明: 公司内部一套自建分布式交易服务平台,在POC稳定性压力测试的时候出现了数据库死锁.(InnoDB引擎)由于保密性,假设是app_test表死锁了. 现象: 发生异常:Deadlock fo ...

  4. 记一次线上MySQL数据库死锁问题

            最近线上项目报了一个MySQL死锁(DealLock)错误,虽说对业务上是没有什么影响的,由于自己对数据库锁这块了解不是很多,之前也没怎么的在线上碰到过.这次刚好遇到了,便在此记录一下 ...

  5. Mysql数据库死锁分析相关概念

    参考博客: mysql死锁问题分析(https://www.cnblogs.com/LBSer/p/5183300.html) mysql insert锁机制(http://yeshaoting.cn ...

  6. 关于在项目中遇到MySQL数据库死锁的问题

    在MySQL中, 当一个事务去更新某条数据, 还没有提交的时候, 第二个事务去更新该数据, 则会出现等待获取锁超时异常: >> Lock wait timeout exceeded; tr ...

  7. mysql数据库死锁的解决方案

    1. 查询锁表信息    show OPEN TABLES where In_use > 0;2. 查看当前数据库锁表的情况    SELECT * FROM information_schem ...

  8. Mybatis-update - 数据库死锁 - 获取数据库连接池等待

    最近学习测试mybatis,单个增删改查都没问题,最后使用mvn test的时候发现了几个问题: update失败,原因是数据库死锁 select等待,原因是connection连接池被用光了,需要等 ...

  9. MySQL 性能优化-数据库死锁监控

    MySQL性能优化-数据库死锁监控 by:授客 QQ:1033553122 1)表锁定 通过检查 table_locks_waited 和 table_locks_immediate 状态变量来分析表 ...

  10. 一个项目中mysql数据库经常死锁的问题解决记录

    1.问题描述 此项目为一个物流系统,需要使用PDA对货物进行入库.备货.出货等操作,在系统开发测试过程中,经常发现死锁问题. 有这样一种业务场景:仓库对备货单上货进行扫码备货后,点击"完成& ...

随机推荐

  1. Mysql 字段加密

    1.PASSWORD() 2.ENCODE(,)   DECODE(,) 3.MD5()4.SHA5() 5.AES_ENCRYPT AES_DECRYPT 加密 select   aes_encry ...

  2. JAVA——》微信分账

    做一个推荐分享的功能,场景:每推荐成功奖励推荐人一定的推荐金. 这里,我就用调用了微信支付分账接口.链接:https://pay.weixin.qq.com/wiki/doc/api/allocati ...

  3. java整合SSM框架

    使用Myeclipse搭建maven项目 准备工作 安装maven 官网下载安装(http://maven.apache.org/)    配置环境变量      配置完后,使用命令行输入mvn -v ...

  4. http hook

    class XMLHttp { request = function(param) {} ; response = function(param) {} ; } let httpCopy = new ...

  5. Selenium 自动化中实现双击操作

    在selenium中,以name定位为例,单击元素的代码为:driver.find_element_by_name("name").click(),那么,实现双击操作的代码能不能写 ...

  6. P1138 第 k 小整数

    P1138 第 k 小整数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) dalao 勿喷,适合新手 思路就是排序加查重,最后判断第k小数.思路十分简单. 刚开始我一直想二维循环查 ...

  7. C++运算符重载引用传参与返回引用的小小心得

    1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 //平面向量类,提供完成向量运算和比较的API 6 //除递增运算符和左移运 ...

  8. java计时器Timer

    基于java的计时器,定时发送消息 package timer; import java.lang.reflect.Array; import java.text.ParseException; im ...

  9. SpringBoot 快速开启事务(附常见坑点)

    序言:此前,我们主要通过XML配置Spring来托管事务.在SpringBoot则非常简单,只需在业务层添加事务注解(@Transactional )即可快速开启事务.虽然事务很简单,但对于数据方面是 ...

  10. 第一次作业:https://edu.cnblogs.com/campus/qdu/DS2020/homework/11165

    大家好,我是信息与计算科学一班的刘宝龙.爱好是看动漫,玩游戏,听音乐,不喜欢户外运动,是一个二次元宅男.但是喜欢交朋友,希望能与班里所有的同学建立良好的同学关系. 自己的强项是与人的交流与沟通,还有遇 ...