mysql innodb引擎RR下的下一个钥匙锁问题

mysql innodb引擎RR下的下一个钥匙锁问题,mysql,innodb,Mysql,Innodb,我在学习mysql innodb引擎下一个密钥锁时遇到了一个问题(在可重复读取级别下) 这是我的表结构和表数据 CREATE TABLE `o` ( `id` int(11) NOT NULL AUTO_INCREMENT, `a` int(10) DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_a` (`a`) ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHAR

我在学习mysql innodb引擎下一个密钥锁时遇到了一个问题(在可重复读取级别下)

这是我的表结构和表数据

CREATE TABLE `o` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `a` int(10) DEFAULT NULL,
      PRIMARY KEY (`id`),
      KEY `idx_a` (`a`)
    ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8

    +----+------+
    | id | a    |
    +----+------+
    |  1 |    1 |
    |  3 |    1 |
    |  5 |    3 |
    |  7 |    6 |
    | 10 |    8 |
    +----+------+
我向字段a添加一个普通索引,然后插入一些数据。 我启动fist事务(我们称之为trx1)并运行以下命令:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from o where a=3 for update;
+----+------+
| id | a    |
+----+------+
|  5 |    3 |
+----+------+
1 row in set (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from o where a=5 for update;
Empty set (0.12 sec)
我想当我运行
select*from o其中a=3进行更新时,mysql将根据下一个键机制锁定(1,3),(3,6)。
接下来,我启动第二个事务(我们称之为trx2)并运行以下命令:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from o where a=3 for update;
+----+------+
| id | a    |
+----+------+
|  5 |    3 |
+----+------+
1 row in set (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from o where a=5 for update;
Empty set (0.12 sec)
令我惊讶的是,为什么trx2成功地执行了命令
select*from o,其中a=5进行更新
。因为我认为trx1已经锁定了5,trx2将阻塞,直到trx1提交


如果有人能回答我的问题,我将不胜感激!!!

经过几天的学习,我终于解决了这个问题。 trx1:
从o中选择*,其中a=3用于更新;
将使用间隙锁锁定(1,6)。 trx2:
从o中选择*其中a=5用于更新;
将使用间隙锁锁定(3,6)。
Gap lock与Gap lock兼容!!!所以trx2不会阻塞。

经过几天的研究,我最终解决了它。 trx1:
从o中选择*,其中a=3用于更新;
将使用间隙锁锁定(1,6)。 trx2:
从o中选择*其中a=5用于更新;
将使用间隙锁锁定(3,6)。 Gap lock与Gap lock兼容!!!因此trx2不会阻塞