【问题标题】:how mysql innodb record lock and insert intention lock works together?mysql innodb 记录锁和插入意向锁如何协同工作?
【发布时间】:2019-12-26 14:44:20
【问题描述】:

InnoDB 的锁指令有很多,但在我的测试中,有些东西仍然让我感到困惑。 MySQL 版本为 5.7,具有可重复读取隔离级别。

drop table if exists t1;
create table if not exists t1(id float,name varchar(20),key idx_id(id));
insert into t1 values (1,'a'),(3,'c'), (4,'d'), (10,'f');

-- session1:
START TRANSACTION;
insert into t1 values (5,'a');   

-- session 2:
update t1 set name='a2' where id > 4 and id < 5;   -- wating for lock

-- session3:
update t1 set name='a2' where id > 5 and id < 10; -- no wait,executed.


据我了解,session1 持有插入意图锁 (4,10),session2 正在等待 X 锁 (4,5),因此被 session 1 阻塞,这是理性的。会话 3 可以等待会话 1 释放锁,但事实是会话 3 只是被执行。这是怎么回事?

【问题讨论】:

  • Heheh Small Point where id &gt; 4 and id &lt; 5 您希望在 4 和 5 之间出现哪些整数? 当我往另一个方向看时,数学是否发生了变化:)
  • InnoDB 执行行级锁定(不是表级)。在 session1 中,您正在插入带有 id = 5 的行,因此任何其他尝试访问带有 id = 5 的行的会话都必须等待锁定释放。现在,会话 3 中的查询正在跳过该特定行 (id &gt; 5),因此会话 3 不需要等待任何内容。
  • 如果会话 1 只是有 id=5 的行级锁定行,为什么会话 2 正在等待

标签: mysql


【解决方案1】:

在会话 1 执行 START TRANSACTION; insert into t1 values (5,'a'); 之后,select * from performance_schema.data_locks; 的输出是:

+--------+--------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+-----------+-------------+-----------+
| ENGINE | ENGINE_LOCK_ID                       | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE | LOCK_STATUS | LOCK_DATA |
+--------+--------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+-----------+-------------+-----------+
| INNODB | 139675093921992:1063:139675020906192 |                  2117 |        52 |       31 | test          | t1          | NULL           | NULL              | NULL       |       139675020906192 | TABLE     | IX        | GRANTED     | NULL      |
+--------+--------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+-----------+-------------+-----------+

在会话 2 执行 update t1 set name='a2' where id &gt; 4 and id &lt; 5; 之后,输出为:

+--------+---------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+---------------+-------------+----------------------------+
| ENGINE | ENGINE_LOCK_ID                        | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE     | LOCK_STATUS | LOCK_DATA                  |
+--------+---------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+---------------+-------------+----------------------------+
| INNODB | 139675093921144:1063:139675020900048  |                  2118 |        49 |       29 | test          | t1          | NULL           | NULL              | NULL       |       139675020900048 | TABLE     | IX            | GRANTED     | NULL                       |
| INNODB | 139675093921144:2:5:6:139675020897056 |                  2118 |        49 |       29 | test          | t1          | NULL           | NULL              | idx_id     |       139675020897056 | RECORD    | X             | WAITING     | 0x0000A040, 0x000000000208 |
| INNODB | 139675093921992:1063:139675020906192  |                  2117 |        52 |       31 | test          | t1          | NULL           | NULL              | NULL       |       139675020906192 | TABLE     | IX            | GRANTED     | NULL                       |
| INNODB | 139675093921992:2:5:6:139675020903280 |                  2117 |        49 |       29 | test          | t1          | NULL           | NULL              | idx_id     |       139675020903280 | RECORD    | X,REC_NOT_GAP | GRANTED     | 0x0000A040, 0x000000000208 |
+--------+---------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+---------------+-------------+----------------------------+

会话3执行update t1 set name='a2' where id &gt; 5 and id &lt; 10;后,输出为:

+--------+---------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+-----------------+-----------------------+-----------+---------------+-------------+----------------------------+
| ENGINE | ENGINE_LOCK_ID                        | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME      | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE     | LOCK_STATUS | LOCK_DATA                  |
+--------+---------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+-----------------+-----------------------+-----------+---------------+-------------+----------------------------+
| INNODB | 139675093922840:1063:139675020912224  |                  2119 |        50 |       30 | test          | t1          | NULL           | NULL              | NULL            |       139675020912224 | TABLE     | IX            | GRANTED     | NULL                       |
| INNODB | 139675093922840:2:5:5:139675020909312 |                  2119 |        50 |       30 | test          | t1          | NULL           | NULL              | idx_id          |       139675020909312 | RECORD    | X             | GRANTED     | 0x00002041, 0x000000000203 |
| INNODB | 139675093922840:2:4:5:139675020909656 |                  2119 |        50 |       30 | test          | t1          | NULL           | NULL              | GEN_CLUST_INDEX |       139675020909656 | RECORD    | X,REC_NOT_GAP | GRANTED     | 0x000000000203             |
| INNODB | 139675093921144:1063:139675020900048  |                  2118 |        49 |       29 | test          | t1          | NULL           | NULL              | NULL            |       139675020900048 | TABLE     | IX            | GRANTED     | NULL                       |
| INNODB | 139675093921144:2:5:6:139675020897056 |                  2118 |        49 |       29 | test          | t1          | NULL           | NULL              | idx_id          |       139675020897056 | RECORD    | X             | WAITING     | 0x0000A040, 0x000000000208 |
| INNODB | 139675093921992:1063:139675020906192  |                  2117 |        52 |       31 | test          | t1          | NULL           | NULL              | NULL            |       139675020906192 | TABLE     | IX            | GRANTED     | NULL                       |
| INNODB | 139675093921992:2:5:6:139675020903280 |                  2117 |        49 |       29 | test          | t1          | NULL           | NULL              | idx_id          |       139675020903280 | RECORD    | X,REC_NOT_GAP | GRANTED     | 0x0000A040, 0x000000000208 |
+--------+---------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+-----------------+-----------------------+-----------+---------------+-------------+----------------------------+

所以,会话 2 被阻止的原因是:它请求 next-key lock (4, 5],即 (4, 5) gap lock 加上 5 index-record lock,但会话 1 持有 5 index-record lock。而会话3没有被阻塞的原因是:它请求next-key lock (5, 10](5, 10) gap lock加上10 index-record lock,没有人持有10 index-record lock

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-05
    • 1970-01-01
    相关资源
    最近更新 更多