mysql> select * from information_schema.innodb_locks;
+---------------+-------------+-----------+-----------+-------------+------------+------------+-----------+----------+-----------+
| lock_id
| lock_trx_id | lock_mode | lock_type | lock_table | lock_index | lock_space | lock_page | lock_rec | lock_data |
+---------------+-------------+-----------+-----------+-------------+------------+------------+-----------+----------+-----------+
| 38777:390:3:5 | 38777
| X
| RECORD | `test`.`t1` | PRIMARY |
390 |
3 |
5 | 4
|
| 38771:390:3:5 | 38771
| X
| RECORD | `test`.`t1` | PRIMARY |
390 |
3 |
5 | 4
|
+---------------+-------------+-----------+-----------+-------------+------------+------------+-----------+----------+-----------+
根据锁及ICP的知识,此时加锁的情况应该是在索引 idx_t1_bcd 上的b>2 and b<5之间加gap lock, idx_t1_bcd 上的c=2 加 X锁主键 a=3 加 x 锁。
应该a=4上是没有加X锁的,可以进行删除与更改。
但是从session3上的结果来,此时a=4上被加上了X锁。
求大牛解惑,谢谢。
-------
要理解这里为什么 a=4 被锁住了,需要理解 gap lock,锁处理 RR 隔离级别和RC隔离级别的区别等等。
这里的原因如下:
很简单,我们注意到:key_len: 4 和 Extra: Using index condition
这说明了,仅仅使用了索引 idx_t1_bcd 中的 b 一列,没有使用到 c 这一列。c 这一列是在ICP时进行过滤的。所以:
delete from t1 where b>2 and b<5 and c=2 其实锁定的行有:
mysql> select * from t1 where b>2 and b<=6; +---+---+---+---+------+ | a | b | c | d | e | +---+---+---+---+------+ | 3 | 3 | 2 | 2 | c | | 4 | 3 | 1 | 1 | d | | 6 | 6 | 4 | 4 | f | | 7 | 4 | 5 | 5 | g | +---+---+---+---+------+ 4 rows in set (0.00 sec)
所以显然 delete from t1 where a=4 就被阻塞了。那么为什么 delete from t1 where a=6 也会被阻塞呢???
这里 b<=6 的原因是,b 列中没有等于 5 的记录,所以 and b<5 实现为锁定 b<=6 的所有索引记录,这里有等于号的原因是,如果我们不锁定 =6 的索引记录,那么怎么实现锁定 <5 的gap 呢?也就是说锁定 b=6 的索引记录,是为了实现锁定 b< 5 的gap。也就是不能删除 b=6 记录的原因。
而这里 b >2 没有加等于号(b>=2) 的原因,是因为 b>2的这个gap 是由 b=3这个索引记录(的gap)来实现的,不是由 b=2索引记录(的gap) 来实现的,b=2的索引记录的gap lock只能实现锁定<2的gap,b>2的gap锁定功能,需要由 b=3的索引记录对应的gap来实现(b>2,b<3的gap)。
所以我们在session2中可以删除:a=1,2,5,8的记录,但是不能删除 a=6(因为该行的b=6)的记录。
如果我们使用 RC 隔离级别时,则不会发生阻塞,其原因就是: