专栏首页我的技术专栏记一次数据库死锁

记一次数据库死锁

业务新上了一个功能,在发布的过程中,系统报出了数据库死锁异常:

com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction

死锁发生在一个事务中,事务对多个表进行了操作。在报错日志中,死锁发生在tableA与tableB。一开始怀疑此次发布的某个改动中对上面这两张表新增了select或update操作。将注意力用在排查这个问题上。排查后发现没有相关的变更,又猜测是否是由于更改造成并发请求进来,接口原来是有加分布式锁的,需求更改中缩小了分布式锁的粒度,确实是有可能造成并发请求。但很快又否定了,秒杀场景下的并发量尚且不会发生死锁,何况是这个接口?觉得问题应该别有所在。先回滚了需求后,联系dba执行了命令SHOW ENGINE INNODB STATUS将死锁日志拉取了出来:

从死锁日志可以看到事务(1)TRANSACTION尝试更新表A,等待表A的锁(1)WATING FOR THIS LOCK TO BE GRANTED.但此时另外一个事务(2)TRANSACTION已经持有了表A的锁:(2)HOLDS THE LOCK(S),同时也在等待表B的锁(2)WATING FOR THIS LOCK TO BE GRANTED. 情况可能如下所示:

事务(1)

事务(2)

持有表1的写锁,并更新了表1

等待表1的写锁

等待表2的写锁

由于事务2一直都获取不到表2的写锁,事务2无法提交,因此事务2持有的表1锁没有释放(在事务执行过程中,如果有加锁操作,这个锁需要等事务提交时释放),导致事务1一直在等待表1的写锁,从而最终导致死锁。那么表2的写锁被哪个事务持有了?有没有可能是事务1?也即是下面这种情况:

事务(1)

事务(2)

持有表2的写锁,并更新了表2

持有表1的写锁,并更新了表1

等待表1的写锁

等待表2的写锁

由于更新的是同一个用户的同一行记录,这种情况可能在sql执行顺序不一致所导致,所以对比了需求变更前后的事务逻辑,果然发现了端倪:

变更前:

事务开始
「
    更新表1
    更新表2
」
事务提交

变更后:

事务开始
「
    更新表2
    更新表1
」
事务提交

在发布的过程中,有部分机器的代码处于变更前,有部分机器的代码处于变更后,最终导致了上述的死锁问题。此时原因已经明了,但是疑惑的是为什么死锁出现时马上就报错,不会进行等待?查阅文档发现:死锁检测开了后,发生死锁会立马回滚。死锁检测关闭,锁等待超时时间这个设置才会生效:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 抽奖系统的流量削峰方案

    如果观看抽奖或秒杀系统的请求监控曲线,你就会发现这类系统在活动开放的时间段内会出现一个波峰,而在活动未开放时,系统的请求量、机器负载一般都是比较平稳的。为了节省...

    Tencent JCoder
  • [Golang]一道考察defer与命名返回值的题目

    Tencent JCoder
  • 关于JVM内存的N个问题

    JVM的内存划分中,有部分区域是线程私有的,有部分是属于整个JVM进程;有些区域会抛出OOM异常,有些则不会,了解JVM的内存区域划分以及特征,是定位线上内存问...

    Tencent JCoder
  • 进程死锁

    操作系统中有若干进程并发执行,它们不断申请、使用、释放系统资源,虽然系统的进程协调、通信机构会对它们进行控制,

    Yif
  • redis 的过期策略都有哪些?内存淘汰机制都有哪些?手写一下 LRU 代码实现?

    所谓定期删除,指的是 redis 默认是每隔 100ms 就随机抽取一些设置了过期时间的 key,检查其是否过期,如果过期就删除。

    IT技术小咖
  • 融完5亿美元创始人出局?腾讯投资的明星无人车公司Zoox地震了

    据外媒The Information报道,据知情人士透露,一手将Zoox带大的“亲妈”Tim Kentley-Klay已经离开公司,并卸下CEO一职。

    量子位
  • 关于Redis的几件小事 | Redis的数据类型/过期策略/内存淘汰

    这个是类似map的一种结构,这个一般就是可以将结构化的数据,比如一个对象(前提是这个对象没嵌套其他的对象)给缓存在redis里,然后每次读写缓存的时候,可以就操...

    王知无
  • 关于Redis的几件小事 | Redis的数据类型/过期策略/内存淘汰

    这个是类似map的一种结构,这个一般就是可以将结构化的数据,比如一个对象(前提是这个对象没嵌套其他的对象)给缓存在redis里,然后每次读写缓存的时候,可以就操...

    暴走大数据
  • MongoDB干货篇之查询数据

    爱撒谎的男孩
  • R语言相识生物信息学

    R在生物信息分析中有着极其重要的重要,无论我们做什么样的分析,我们都离不开强大的R。无论是统计学分析,还是想得到漂亮的图形,R都成了我们工作必不可少的一部分。无...

    一粒沙

扫码关注云+社区

领取腾讯云代金券