为什么一条条锁会造成死锁?
有时候,我们需要修改某一个表的数据,但是那个表的数据是大家都可以修改的,比如下面的一个场景:
用户获得奖品1,2,3,4,5,6,然后每个奖品要去扣库存,如果不注意的话,可能会有如下操作
原因分析
for(奖品ID序号)
select * from 奖品表 where id=奖品id for update
扣库存
猛一看没毛病,每条记录都要修改库存,完全OK!
其实这段代码在多线程的情况下会高可能性造成死锁的,分析如下。
线程A进来了,开始一条条执行锁:
锁1
锁2
锁3
线程B进来了,开始一条条执行锁
锁6
锁5
锁4
然后线程A要锁4,5,6,因为被B先锁了只能等待,线程B要锁1,2,3也是一样因为被A先锁了要等待,所以就造成死锁了。
解决办法
可以执行如下语句一起锁
select * from 奖品表 where id in(奖品序号) for update
这样子就不会造成死锁了,并且不会有多次的TCP交互,提高了应用的效率。
为什么不能链表锁
举个例子,有时候我们要进行行锁修改记录,但是要锁的表信息不够,此时你可能会做如下的操作:
select t1.seq,t1.status,t2.info from 要锁的表 t1,要查数据的表 t2 where t1.seq='ss' and t1.a=t2.a for update
看起来是一下子就把想要的数据查回来了,可要查数据的表里的数据并不是属于自己的数据,别人也要用,但是也被锁住了,极大的降低了程序的效率。