首页 > 解决方案 > RR下mysql innodb engine next-key lock问题

问题描述

我在学习mysql innodb engine next-key lock时遇到问题(在Reapeatable Read级别下)。

这是我的表结构和表数据。

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 添加一个普通索引,然后插入一些数据。我开始第一个事务(我们称为 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)

我认为当我运行时select * from o where a=3 for update,mysql 将基于 next-key 机制锁定 (1,3],(3,6)。接下来,我开始第二个事务(我们调用 trx2)并运行以下命令:

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 where a=5 for update成功执行命令。因为我认为 trx1 已经锁定了 5 并且 trx2 会阻塞直到 trx1 提交。

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

标签: mysqlinnodb

解决方案


经过几天的研究,我最终解决了它。trx1:select * from o where a=3 for update;将使用间隙锁锁定(1,6)。trx2:select * from o where a=5 for update;将使用间隙锁锁定(3,6)。间隙锁与间隙锁兼容!!!所以 trx2 不会阻塞。


推荐阅读