Deadlock found when trying to get lock(死锁)问题解决

今天压测用户中心的登录接口。发现这个接口在并发下几乎不可用,错误率70%。

查看后台日志全是:

Deadlock found when trying to get lock(死锁)问题解决_第1张图片

登录接口出现死锁了。

看了下代码,登录中做了更新用户登录时间,插入用户log。查询数据库,发行用户更新和插入log都会lock wait

Deadlock found when trying to get lock(死锁)问题解决_第2张图片

判断可能是在压测同一个用户登录时,某个请求中的事务读取到了另一个请求里事务未提交的数据。从而需要等待之前的事务提交。(幻读)

然后将事务隔离机制改成SERIALIZABLE。

@Transactional(isolation= Isolation.SERIALIZABLE)。

然而并不能解决问题。

后来发现问题出现在记录用户日志上

Deadlock found when trying to get lock(死锁)问题解决_第3张图片

save(user)后,user对象是持久态,然后把持久态的user塞到userlog对象里

虽然这里没配置@cascade,但是如果对象是持久态的话,会默认级联更新。

所以在后续我执行save(userlog)时,有对这个user update了一遍。照成死锁。

 

然后我去除了manyToOne的依赖,改成ID。

结果fuck,问题依然存在!

 

最后看到一篇文章:

https://www.percona.com/blog/2006/12/12/innodb-locking-and-foreign-keys/

才发现罪魁或者是外键,userLog表有外键。

当插入一条userLog时,会把关联的user数据给锁了,然后对这个user的更新操作很容易死锁。

删除外键后,解决问题。

你可能感兴趣的:(java,mysql,死锁)