时间:2021-07-01 10:21:17 帮助过:21人阅读
案例2:
在开发中,经常会做这类的判断需求:根据字段值查询(有索引),如果不存在,则插入;否则更新。
以id为主键为例,目前还没有id=22的行 Session1: select * from t3 where id=22 for update; Empty set (0.00 sec) session2: select * from t3 where id=23 for update; Empty set (0.00 sec) Session1: insert into t3 values(22,‘ac‘,‘a‘,now()); 锁等待中…… Session2: insert into t3 values(23,‘bc‘,‘b‘,now()); ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
当对存在的行进行锁的时候(主键),mysql就只有行锁。
当对未存在的行进行锁的时候(即使条件为主键),mysql是会锁住一段范围(有gap锁)
锁住的范围为:
(无穷小或小于表中锁住id的最大值,无穷大或大于表中锁住id的最小值)
如:如果表中目前有已有的id为(11 , 12)
那么就锁住(12,无穷大)
如果表中目前已有的id为(11 , 30)
那么就锁住(11,30)
对于这种死锁的解决办法是:
insert into t3(xx,xx) on duplicate key update `xx`=‘XX‘;
用mysql特有的语法来解决此问题。因为insert语句对于主键来说,插入的行不管有没有存在,都会只有行锁。
案例3:
直接上情景:
mysql> select * from t3 where id=9 for update; +----+--------+------+---------------------+ | id | course | name | ctime | +----+--------+------+---------------------+ | 9 | JX | f | 2016-03-01 11:36:30 | +----+--------+------+---------------------+ row in set (0.00 sec) Session2: mysql> select * from t3 where id<20 for update; 锁等待中 Session1: mysql> insert into t3 values(7,‘ae‘,‘a‘,now()); ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
这个跟案例一其它是差不多的情况,只是session1不按常理出牌了,
Session2在等待Session1的id=9的锁,session2又持了1到8的锁(注意9到19的范围并没有被session2锁住),最后,session1在插入新行时又得等待session2,故死锁发生了。
这种一般是在业务需求中基本不会出现,因为你锁住了id=9,却又想插入id=7的行,这就有点跳了,当然肯定也有解决的方法,那就是重理业务需求,避免这样的写法。
转:https://www.cnblogs.com/zejin2008/p/5262751.html
附记,推荐两篇好文章
案例4:
http://hedengcheng.com/?p=844
MySQL 加锁处理分析:
http://hedengcheng.com/?p=771
Mysql并发时经典常见的死锁原因及解决方法
标签:业务 values 情况 根据 最大 避免 mysql 页面锁 页面