mysql批量update死锁

1、背景

        项目使用了多线程,同时调用service中的update方法更新数据,之前由于在update方法上加了synchronized做了线程同步,没有出现mysql update死锁的问题。但是由于update更新耗时比较长,synchronized锁住对象,导致调用service中的其他方法阻塞,效率地下,于是优化synchronized,移到方法内部的同步代码段,然后虽然效率提高了,但是mysql总是出现死锁的bug:

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

2、发生原因

T1:begin tran select * from table lock in share mode update table set column1='hello'

T2:begin tran select * from table lock in share mode update table set column1='world'

假设 T1 和 T2 同时达到 select,T1 对 table 加共享锁,T2 也对 table 加共享锁,当 T1 的 select 执行完,准备执行 update 时,根据锁机制,T1 的共享锁需要升级到排他锁才能执行接下来的 update.在升级排他锁前,必须等 table 上的其它共享锁(T2)释放,同理,T2 也在等 T1 的共享锁释放。于是死锁产生了。

因此,当sql发出一个update请求之后,数据库会对表中的每条记录加上共享锁。然后数据库会根据where条件,将符合条件的记录转换为排他锁(mysql innodb默认对索引加锁),我们的多个线程update时,就出现了上面的情况,发生了死锁。

 

参考:

https://uule.iteye.com/blog/2422193

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值