一只正在奋斗的小猪 2021-03-11 11:02 采纳率: 0%
浏览 55

关于事务中死锁的一个问题

各位大神,小弟在这里先祝大家新年快乐。

小弟最近遇到一个关于mysql事务的问题,由于技术底子太单薄,希望借助各位大神的力量解决一下。

问题描述:

现在有一个账户,该账户是为集成我们服务的第三方平台分配的,作用基本是用于扣款。

在账户表中有一个次数(账户金额)的一个字段,账户表使用的存储引擎为InnoDB。

第三方平台的终端用户在使用他们的某一项功能时(其实该功能时我们提供的),第三方平台来调我们的接口,然后我们就减一次上面说的那个次数(账户金额)。

其实,说白了就是减库存的问题。

第三方平台用户数量很多,可能会大量并发的过来使用该功能。

我方平台的这个接口,加了事务控制,使用的是spring4.3.2 + mybatis3.4.1

上面说了,账户表的存储引擎为InnoDB。所以,每次调用我们接口,我们在扣款的时候,应该是开启了行级锁,把该账户的这条数据锁住了。以后来的扣款,估计都在等待。

最近经常报出异常为:
Deadlock found when trying to get lock; try restarting transaction

我现在很疑惑,为什么是死锁?而不是等待锁超时呢?
如果为:Lock wait timeout exceeded; try restarting transaction
我想我可能会理解,但是Deadlock我就不解了。

因为,第一个扣款线程进来先锁住那行记录,第二第三...的扣款线程就在外面一直等着。
第一个线程提交事务,释放InnoDB行级锁,第二个线程进来获取锁...应该为这样的顺序。
mysql有一个等待锁的超时时间,如果超时,那么线程直接timeout。

这里应该不存在死锁的情况啊?我理解死锁应该为,多方牵制导致锁永远也释放不掉。
我这种情况不是释放不掉啊,线程提交或回滚就释放了的啊?

各位大神,帮忙解释解释这个问题吧,停基础的,但是小弟...不会..

  • 写回答

1条回答 默认 最新

  • 梦醉天下 2021-03-11 11:15
    关注

    按照你的描述,逻辑理解应该没问题,但是导致死锁,那我建议explain一下update语句,看看实际update的时候是否是走的key或者索引,如果条件并没有update唯一行,很有可能导致这样的问题。如果单个账户的扣款并发也比较大,那么建议在代码层也做并发控制。

    评论

报告相同问题?

悬赏问题

  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog