有一段业务代码,不知道会不会死锁

2023-02-07 18:32:52 +08:00
 dengji85

线上环境偶尔一个待办无法处理,服务器 cpu100%,原因时数据库死锁了,因为逻辑是这样

有 2 条 id 分别为 1 ,2 的待办数据
处理 1 后,自动启一个线程更新 2
处理 2 后,自动启一个线程更新 1
因为处理比较耗时,用户可能反复重试,看起来会有死锁,但是自动更新是异步,不在一个事务里,这种情况会产生死锁吗?
service{
    update(){
    //事务
    //耗时较长
    }
}

WebControllerMethod(){
    update(id:1)
    ThreadPoolTaskExecutor.execute(() -> {
        update(id:2)
    }
}
1255 次点击
所在节点    程序员
5 条回复
googlefans
2023-02-07 19:01:27 +08:00
去问问 chatgpt
xmarsman
2023-02-08 09:46:28 +08:00
chatgpt 的回复如下:
----------------------------------------------------------------------------
上面的代码存在以下问题:

update 方法没有返回值,但却使用了 return 语句。
ThreadPoolTaskExecutor.execute 中没有对 update 方法进行调用,而是直接把 update 当作了一个代码块,这是错误的。
缺少括号,在 ThreadPoolTaskExecutor.execute 后面的代码是无法正常编译的。
Jtyczc
2023-02-08 12:03:46 +08:00
增加一个中间状态,处理中,然后开始处理前,判断一下异步更新是否处理中,如果处理中就告诉用户先等待,如果没有,去更新。
tairan2006
2023-02-08 13:35:03 +08:00
update(id:1)和 update(id:2)会有并发,如果你只是加行锁,两边应该没啥关联,当然具体的情况需要看业务逻辑。

如果用户反复尝试,你应该第二次直接报错,而不是走到业务逻辑里。可以通过 redis 搞个分布式锁,或者显式的 select for update 加锁(MySQL 的话)。
lookStupiToForce
2023-02-08 15:36:46 +08:00
不了解你用的啥框架去连的什么数据库,初看,感觉触发的是超时锁,不是真死锁

真死锁得是两个进程,各自在其线程内 /事务内
pid1: 先获取 lock1——do something——再获取 lock2
pid2: 先获取 lock2——do something——再获取 lock1

然后 pid1 因为 pid2 锁住了 lock2 ,导致 pid1 无法进入后续步骤,无法结束,进而 [无法释放 lock1] ,
进一步导致 pid2 无法获得 lock1 也无法结束无法释放 lock2 。
( pid1 try lock2 -- failed because pid2 hold lock2 -- pid1 keep holding lock1 -- pid2 try lock1 and failed -- pid2 keep holding lock2 -- pid1 try lock2......)

产生死锁的点在于,pid1 和 pid2 在不能获取第二步骤的锁( pid1 拿 lock2 ,pid2 拿 lock1 )的时候, [无法释放第一个锁] 。

但如果
WebControllerMethod(){
update(id:1)
ThreadPoolTaskExecutor.execute(() -> {
update(id:2)
}
}
里的 update(id:1) 可以在执行 ThreadPoolTaskExecutor.execute(() -> {update(id:2)} 前,就释放 id:1 的锁,那理论上就不存在死锁了

所以怀疑是超时锁,因为许许多多因为用户反复重试导致的 pid1 在不停 lock2 and update 2 ,导致你新的 pid2 lock2 fail 进而报了超时。

除非有种可能,你的 commit/rollback 不在 update 方法里,而在 WebControllerMethod 里,那么你俩线程其实是共用同一个连接同一个事务,这样就肯定有死锁的情况了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/914024

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX