先说结论:
- MySQL
for update
加的是独占锁,而且如果对应的索引是唯一索引加的是行锁,一个事务加锁了,另一个事务应该被阻塞了。 - 但是如果该查询条件对应的记录不存在,则加了gap锁。
- 同时如果并发执行insert语句,需要insert意向锁,和gap锁是冲突的,容易产生死锁
有如下的表:
1 | CREATE TABLE `test` ( |
表中数据如下:
1 |
|
有两个并发的事务执行相同的SQL:
1 | START TRANSACTION; |
第二个事务会出现死锁,退出后随即第一个事务insert执行成功。
1 | mysql> START TRANSACTION; |
该例子和幻读挺类似的。但是for update应该加的是独占锁,而且如果对应的索引是唯一索引加的是行锁,一个事务加锁了,另一个事务应该被阻塞了。但是如果该查询条件对应的记录不存在,加的则是gap锁,该例子中锁的范围是(11,16),不包括11,16,gap是互相兼容的,另一个事务不会阻塞。执行insert语句时,需要insert意向锁,和gap锁是冲突的,所以产生了死锁。