问题:
1.为什么session_1执行mysql> select * from emp where empid = 102 for update;后,出现的间隙锁只是102本身还是还有其他?
2.为什么session_2执行mysql>insert into emp(empid,...) values(201,...); 会出现加锁?
...全文
82521打赏收藏
关于间隙锁
所使用到的表: 该表中插入1,2,3,....,101 执行如下操作: 问题: 1.为什么session_1执行mysql> select * from emp where empid = 102 for update;后,出现的间隙锁只是102本身还是还有其他? 2.为什么session_2执行mysql>insert into emp(empid,...) values(201,...); 会出现加锁?
mysql> insert into test values(1),(3),(5),(11);
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
为什么session_2上面插入语句出现锁等待的情况?InnoDB是行锁,在session_1里面锁住了a=5的行,其他他应该不受影响。为什么?
分析如下:
分析如下:
因为InnoDB对于行的查询采用了Next-Key Lock的算法,锁定的不是单个值,而是一个范围。上面的索引有1,3,5,11,被Next-Key Locking的区间为:
[-无穷,1),[1,3),[3,5),[5,11),[11,+无穷)
下面我们就可以解释上面的出现的问题了:
mysql> select * from test where id=5 for update;
+------+
| id |
+------+
| 5 |
+------+
1 row in set (0.00 sec)
该SQL语句锁定的范围是[3,5),[5],[5,11),所以当我们视图插入5,6,7,8,9,10会被锁住。而插入非这个范围的值都是正常的。
看for update的字面意思感觉就挺能明白为啥insert的时候加锁了啊,而且应该是表锁,因为mysql不确定你select完了后是否update这条记录的主键,如果你刚好update emp set empid=201;那么自然跟insert的那个冲突了。除非你能事先告诉mysql你select完后只更新102,就只会有行锁了。