MySQL 中隔离级别 RC 与 RR 的区别(3)

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 隔离级别时,则不会发生阻塞,其原因就是:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/ca76e42465f55c8e0d16d71be54596cd.html