广告
返回顶部
首页 > 资讯 > 数据库 >innodb中怎么实现一个存储引擎锁
  • 377
分享到

innodb中怎么实现一个存储引擎锁

2024-04-02 19:04:59 377人浏览 薄情痞子
摘要

本篇文章为大家展示了innodb中怎么实现一个存储引擎锁,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。| innodb存储引擎行锁的算法数据库对锁的使用是

本篇文章为大家展示了innodb中怎么实现一个存储引擎,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

| innodb存储引擎行锁的算法

数据库对锁的使用是为了支持对共享资源进行并发的访问,提供数据的完整性和一致性。innodb存储引擎提供了表锁、行锁和意向锁用来实现事物在不同粒度上进行上锁,从而提高数据库的并发访问,并且保证数据的完整性和一致性。

innodb存储引擎的锁类型

innodb存储引擎是通过给索引上的索引项加锁来实现行锁,这种特点也就意味着,只要通过索引条件检索数据,innodb才会使用行级锁,否则会使用表锁。innodb存储引擎有以下锁类型:

  • 1.共享锁和排他锁(Shared and Exclusive Locks)

  • 2.意向锁(Intention Locks)

  • 3.记录锁(Record Locks)

  • 4.间隙锁(Gap Locks)

  • 5.Next-Key Locks

  • 6.插入意向锁(Insert Intention Locks)

  • 7.自增锁(AUTO-INC Locks)

  • 8.空间索引谓词锁(Predicate Locks for Spatial Indexes)

(1)共享锁和排他锁(Shared and Exclusive Locks)
  • innodb实现标准行级锁,其中有两种类型的锁,共享锁(S)和独占锁(X)。

    • 1.共享锁,允许一个事务去读一行,阻止其他事务获得相同数据集的排它锁。

    • 2.排它锁,允许获取排他锁的事务更新数据,阻止其他事务取得相同的数据集的共享读锁和排他锁。

  • 如果事务T1持有一行记录的共享锁,那么另一个不同的事务T2对该行记录的锁定如下:

    • 1.如果事务T2对该行的请求是一个S锁,那么事务T1和事务T2可以共同对该行记录持有同一把S锁。

    • 2.如果事务T2对该行的请求是一个X锁,那么事务T2不可能马上获得对该行记录的X锁,必须要等到事务T1将该记录的S锁释放,才可以对该行记录持有X锁。

    • 3.如果事务T1持有第 r 行的独占(X)锁,那么对于事务T2对该行记录的任何一种请求的锁都不能立即授予。相反,事务T2必须要等到事务T1释放在r 行上的锁。

(2)意向锁(Intention Locks)

innodb存储引擎支持多种粒度锁,允许行锁和表锁共存。为了在多个粒度级别上进行锁定,innodb存储引擎使用意向锁来实现。意向锁是表级锁,它先指明了该事物是那种类型的锁(共享锁或者独占锁),然后去锁定表中某行记录。(我们可以在后面的Gap lock 和 Next-Key Locks 的演示中Mysql 8.0 的infORMation_schema.data_locks 表中显示的信息看到) 

有两种类型的意向锁:

  • 1.意向共享锁(IS),表明事务在一个表中的单个行上设置共享锁。

  • 2.意向独占锁(IX),表明事务在表中的某行设置独占锁。 
    例如,SELECT … LOCK IN SHARE MODE 是IS,而 SELECT … FOR UPDATE 是IX锁。

  • 意向锁的添加方式:

    • 1.在一个事务对一张表的某行添加S锁之前,它必须对该表获取一个IS锁或者优先级更高的锁。

    • 2.在一个事务对一张表的某行添加X锁之前,它必须对该表获取一个IX锁。

  • 表级锁类型兼容性如下图所示: 

innodb中怎么实现一个存储引擎锁

  • 如果与现有锁相兼容,则授予事务请求的锁,但如果它与之冲突,则不会,并且该事务一直等待直到冲突的现有锁被释放。如果所请求的锁与持有的锁冲突是不可能被授予,因为这将会导致死锁,并且返回错误。

  • 意向锁不会阻塞任何请求,除非将这个表锁住,例如,LOCK TABLE …. WRITE。意向锁的主要目的是显示某人正在锁定一行,或者在锁定表中的一行数据。

(3)记录锁(Record Locks)

Record Lock总是会去锁定主键、非空的唯一性索引对应的索引记录,如果在建innodb表时并没有创建任何索引,innodb会对6字节的rowid的主键来进行锁定。Read-Uncommited/RC级别都是使用该方式来进行加锁。 

Record Lock的主要目的:行锁可以防止不同事务版本的数据修改提交时造成数据冲突的情况。

admin@localhost : test 10:53:27> select * from test;
+------+------+
| id  | xid  |
+------+------+
|    1 |    2 |
|    3 |    3 |
+------+------+
2 rows in set (0.00 sec)
admin@localhost : test 10:53:45> show index from test;
Empty set (0.01 sec)
admin@localhost : test 10:54:05> show create table test;
+-------+---------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                          |
+-------+---------------------------------------------------------------------------------------------------------------------------------------+
| test  | CREATE TABLE `test` (
`id` int(11) DEFAULT NULL,
`xid` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin |
+-------+---------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

下面我们开启2个会话session A 、session B 、session C进行测试

innodb中怎么实现一个存储引擎锁

可以通过INFORMATION_SCHEMA中的innodb_lock_waits、innodb_locks、innodb_trx查看到锁的详细信息

admin@localhost : test 11:10:26> select * from information_schema.innodb_lock_waits;
+-------------------+-------------------+-----------------+------------------+
| requesting_trx_id | requested_lock_id | blocking_trx_id | blocking_lock_id |
+-------------------+-------------------+-----------------+------------------+
| 17660049          | 17660049:589:3:4  | 17660047        | 17660047:589:3:4 |
+-------------------+-------------------+-----------------+------------------+
1 row in set, 1 warning (0.02 sec)
Warning (Code 1681): 'INFORMATION_SCHEMA.INNODB_LOCK_WAITS' is deprecated and will be removed in a future release.
admin@localhost : test 11:10:35> 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      |
+------------------+-------------+-----------+-----------+---------------+-----------------+------------+-----------+----------+----------------+
| 17660049:589:3:4 | 17660049    | X        | RECORD    | `test`.`test` | GEN_CLUST_INDEX |        589 |        3 |        4 | 0x000000000400 |
| 17660047:589:3:4 | 17660047    | X        | RECORD    | `test`.`test` | GEN_CLUST_INDEX |        589 |        3 |        4 | 0x000000000400 |
+------------------+-------------+-----------+-----------+---------------+-----------------+------------+-----------+----------+----------------+
2 rows in set, 1 warning (0.00 sec)
admin@localhost : test 11:11:31> select * from information_schema.innodb_trx\G
*************************** 1. row ***************************
                trx_id: 17660049
            trx_state: LOCK WAIT
          trx_started: 2018-05-24 11:10:33
trx_requested_lock_id: 17660049:589:3:4
      trx_wait_started: 2018-05-24 11:10:33
            trx_weight: 3
  trx_mysql_thread_id: 15
            trx_query: update test set xid=5 where id=3
  trx_operation_state: fetching rows
    trx_tables_in_use: 1
    trx_tables_locked: 1
      trx_lock_structs: 3
trx_lock_memory_bytes: 1136
      trx_rows_locked: 2
    trx_rows_modified: 0
trx_concurrency_tickets: 0
  trx_isolation_level: READ COMMITTED
    trx_unique_checks: 1
trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
trx_adaptive_hash_latched: 0
trx_adaptive_hash_timeout: 0
      trx_is_read_only: 0
trx_autocommit_non_locking: 0

从information_schema.innodb_locks可以看出session A的事务17660047 与 session C 的事务 17660049 都是对聚集索引上的id=3记录是上排它锁,并且session C 的事务 17660049 在等待session A的事务17660047 的X锁对 id = 3记录的释放。

(4)间隙锁(Gap Locks)
  • Gap Lock:间隙锁只存在于RR隔离级别下的辅助索引中,只锁定一个范围,但不包含记录本身。如果只锁定一个范围,那这个范围是怎样的?

  • Gap Lock的主要目的:间隙锁避免了别的事务插入数据,从而避免了不可重复读现象。

  • Gap Lock的特点:

    • 一个间隙锁可能间隔一个索引值、多个索引值或者是无穷

    • 间隙锁是为了平衡性能和并发的一部分,并且间隙锁只能在RR隔离级别下使用

    • 对于使用唯一索引查找数据,是不需要使用间隙锁,但是并不包含查询条件中只包含多列中的某些列,唯一索引在这样的情况下,会使用间隙锁来锁定。

    • 不同的事务可以在一个间隙锁中持有冲突的锁。如果事务A在一个间隙锁中持有的是共享的间隙锁(gap S-lock),而事务B持有事务A在相同间隙的独占间隙锁(gap X-lock)。该类型的锁冲突间隙锁是允许的,如果a记录被从索引上删除,不同事务在该记录上的间隙锁将被合并。

    • innodb存储引擎的间隙锁范围是完全禁止操作的,这将意味着其他事务无法对间隙锁范围进行插入操作。间隙锁不会阻止不同的事务去获取同样的间隙锁范围,因此间隙锁 gap X-lock 和 gap S-lock 的效果是一样的。

    • 间隙锁可以被显式的禁用。将事务的隔离级别设置为 READ COMMITTED 或者开启 innodb_locks_unsafe_for_binlog=ON (已经被弃用)。在这样的情况下,在查询和索引扫描中禁用间隙锁,并且只适用于外键约束和主键检查。

    • 在使用READ COMMITTED隔离级别或者开启 innodb_locks_unsafe_for_binlog=ON 都可以显式的禁用间隙锁。开启“semi-consistent” 半一致行读取后,Mysql 会过滤掉不匹配的行,并且释放不匹配的行的锁,并且将过滤后数据返回到存储引擎层去更新。

  • 测试步骤 
    在RR隔离级别下,创建一张只有辅助索引的t3表,并且对辅助索引的一个范围使用 for update 查询,插入包含在范围中的值,然后分别对范围的上确界和下确界进行update操作。

admin@localhost : test 03:55:34> set session transaction_isolation='REPEATABLE-READ' ;
Query OK, 0 rows affected (0.00 sec)
admin@localhost : test 03:29:44> show variables like '%lation';
+---------------+-----------------+
| Variable_name | Value          |
+---------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.01 sec)
root@localhost : test1 12:12:40> select * from t3;
+------+------+
| id | xid |
+------+------+
| 1 | 1 |
| 2 | 1 |
| 4 | 3 |
| 7 | 7 |
| 10 | 9 |
+------+------+
5 rows in set (0.00 sec)
root@localhost : test1 12:08:24> show index from t3;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| t3 | 1 | xid | 1 | xid | A | 3 | NULL | NULL | YES | BTREE | | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)

innodb中怎么实现一个存储引擎锁

接下来使用mysql 8.0 中的performance_schema.data_locks 来辅助我们查看这2个事务具体锁的那条记录,和锁的模式等相关信息。

root@localhost : (none) 04:48:29> 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 | 1609:1059 | 1609 | 64 | 63 | test | t | NULL | NULL | NULL | 140152030668888 | TABLE | IX | GRANTED | NULL |
| INNODB | 1609:2:5:4 | 1609 | 64 | 63 | test | t | NULL | NULL | xid | 140152030665848 | RECORD | X,GAP | WAITING | 3, 0x000000000202 |
| INNODB | 1608:1059 | 1608 | 63 | 88 | test | t | NULL | NULL | NULL | 140152030662936 | TABLE | IX | GRANTED | NULL |
| INNODB | 1608:2:5:4 | 1608 | 63 | 88 | test | t | NULL | NULL | xid | 140152030659896 | RECORD | X | GRANTED | 3, 0x000000000202 |
| INNODB | 1608:2:4:4 | 1608 | 63 | 88 | test | t | NULL | NULL | GEN_CLUST_INDEX | 140152030660240 | RECORD | X | GRANTED | 0x000000000202 |
| INNODB | 1608:2:5:5 | 1608 | 63 | 88 | test | t | NULL | NULL | xid | 140152030660584 | RECORD | X,GAP | GRANTED | 7, 0x000000000203 |
+--------+----------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+-----------------+-----------------------+-----------+-----------+-------------+-------------------+
6 rows in set (0.00 sec)

innodb中怎么实现一个存储引擎锁

事务A 造成的锁

1、  | INNODB | 1608:1059 | 1608 | 63 | 88 | test | t | NULL | NULL | NULL | 140152030662936 | TABLE | IX | GRANTED | NULL |
2、 | INNODB | 1608:2:5:4 | 1608 | 63 | 88 | test | t | NULL | NULL | xid | 140152030659896 | RECORD | X | GRANTED | 3, 0x000000000202 
事务A对test库的t表上的辅助索引xid  对xid=3记录加 RECORD 锁,0x000000000202 表示其对应的6字节的rowid的位置指针。
3、| INNODB | 1608:2:4:4 | 1608 | 63 | 88 | test | t | NULL | NULL | GEN_CLUST_INDEX | 140152030660240 | RECORD | X | GRANTED | 0x000000000202 |
由于test库的t表只有一个非唯一的辅助索引xid,会使用6字节的rowid来作为聚集索引,事务A造成的锁会对 辅助索引xid=3 记录对应的聚集索引也加X锁,相当于将辅助索引xid=3的整条行记录都上X锁
4、| INNODB | 1608:2:5:5 | 1608 | 63 | 88 | test | t | NULL | NULL | xid | 140152030660584 | RECORD | X,GAP | GRANTED | 7, 0x000000000203 |
记录xid=7 上虽然添加的锁为X,GAP锁,但是并没有对辅助索引xid=7对应的聚集索引添加X锁,所以辅助索引xid=7这条记录并没有上X锁,实际上只是用来表示与前一行记录在 (3,7)区间构成间隙锁。

事务B造成的锁

| INNODB | 1609:1059 | 1609 | 64 | 63 | test | t | NULL | NULL | NULL | 140152030668888 | TABLE | IX | GRANTED | NULL |
| INNODB | 1609:2:5:4 | 1609 | 64 | 63 | test | t | NULL | NULL | xid | 140152030665848 | RECORD | X,GAP | WAITING | 3, 0x000000000202 |
事务B在事务A已经持有锁的情况下,进行插入(id,xid) ====>(1,2) 发现(1,3)存在间隙锁。无法进行插入操作。

(5)Next-Key Lock

Next-Key Lock 是结合了Gap Lock和Record Lock的合并,其设计目的主要是为解决RR级别下的幻读问题。该锁定方式相对于Gap Lock和Record Lock是带闭合区间的范围锁定。 

以下介绍其特点:

  • Innodb存储引擎使用Next-Key Locks 只在 REPEATABLE READ 隔离级别下。

  • 当进行查询或者索引扫描时,innodb存储引擎以行锁的方式进行锁定,它会将符合条件的索引记录使用S锁或者X锁。因此,行级锁实际上就是对索引记录上锁。Next-Key Locks会影响 gap锁 的上一个索引记录,也就是Next-Key Locks是由索引记录锁加上gap 锁组成。如果一个会话,在索引记录R上有一个共享或者独占锁,在索引记录R与上一个索引记录之间的间隙,另一个会话不可能插入一个新的索引记录。

  • Next-Key Locks在某些情况下可以锁住索引记录的最大值和大于最大值的范围,大于最大索引记录的范围称为 "supremum pseudo-record"伪记录。 
    注:官方文档并没有介绍对Next-Key Lock介绍太多,所以我们通过以下场景来对Next-Key Lock的特点进行说明。

  • 场景一:RR隔离级别下对一张只有主键的表进行操作

    • 主键只是由一列构成

root@localhost : test1 07:58:18> select * from t1;
+----+------+
| id | xid |
+----+------+
| 1 | 1 |
| 2 | 1 |
| 4 | 3 |
| 7 | 7 |
| 10 | 9 |
+----+------+
5 rows in set (0.00 sec)
root@localhost : test1 07:58:10> show index from t1;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| t2 | 0 | PRIMARY | 1 | id | A | 4 | NULL | NULL | | BTREE | | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)

innodb中怎么实现一个存储引擎锁

root@localhost : (none) 05:37:52> 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 | 1611:1060 | 1611 | 63 | 94 | test | t1 | NULL | NULL | NULL | 140152030662936 | TABLE | IX | GRANTED | NULL |
| INNODB | 1611:3:4:4 | 1611 | 63 | 94 | test | t1 | NULL | NULL | PRIMARY | 140152030659896 | RECORD | X | GRANTED | 4 |
+--------+----------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+-----------+-------------+-----------+
2 rows in set (0.00 sec)

事务A造成的锁

| INNODB | 1611:1060 | 1611 | 63 | 94 | test | t1 | NULL | NULL | NULL | 140152030662936 | TABLE | IX | GRANTED | NULL |
| INNODB | 1611:3:4:4 | 1611 | 63 | 94 | test | t1 | NULL | NULL | PRIMARY | 140152030659896 | RECORD | X | GRANTED | 4 |
由于我们显示的定义了主键可以看到这里LOCK_DATA=4就是这个表内建的rowid ,说明聚集索引上的id=4的行记录直接被加了X锁,也并没有用到GAP锁。

该场景与GAP锁的场景相比较可以发现,在RR隔离级别下当过滤条件的列是主键或者唯一索引的情况下,因为该列值都是唯一值,innodb存储引擎会对Next-Key Lock进行优化,Next-Key Lock会降级成为Record Lock。换句话说gap锁只存在于RR隔离级别下的辅助索引中,主键和唯一索引由于本身具有唯一约束,不需要gap锁,只有record lock

  • 如果主键由多列构成,但是只使用其中的一列进行查询呢?

root@localhost : test 05:03:13> select * from t3;
+----+-----+------+
| id | xid | name |
+----+-----+------+
| 1 | 1 | a |
| 2 | 1 | b |
| 4 | 3 | c |
| 7 | 7 | d |
| 10 | 9 | e |
+----+-----+------+
5 rows in set (0.00 sec)
root@localhost : test 05:03:18> show index from t3;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+
| t3 | 0 | PRIMARY | 1 | id | A | 5 | NULL | NULL | | BTREE | | | YES |
| t3 | 0 | PRIMARY | 2 | xid | A | 5 | NULL | NULL | | BTREE | | | YES |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+
2 rows in set (0.29 sec)

innodb中怎么实现一个存储引擎锁

root@localhost : (none) 05:05:51> 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 | 2123:1062 | 2123 | 68 | 40 | test | t3 | NULL | NULL | NULL | 139846618228824 | TABLE | IX | GRANTED | NULL |
| INNODB | 2123:5:4:4 | 2123 | 68 | 40 | test | t3 | NULL | NULL | PRIMARY | 139846618225784 | RECORD | X | GRANTED | 4, 3 |
| INNODB | 2123:5:4:5 | 2123 | 68 | 40 | test | t3 | NULL | NULL | PRIMARY | 139846618226128 | RECORD | X,GAP | GRANTED | 7, 7 |
+--------+----------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+-----------+-------------+-----------+
3 rows in set (0.00 sec)

我们看到了什么?可以发现当主键由多列构成时,我们只使用主键列中的一列进行查询时,依然使用到了Next_Key Lock ,为什么这样? 

我们都知道主键的键值是唯一的,但是我们这里定义的主键是primary key(id,xid) 表示的是(id,xid) 组成的键值是唯一的,并不能保证id或者xid的键值是唯一的,所以这里依然使用Next_Key Lock 来进行加锁并没有降级使用Record lock 来进行加锁。

  • 那当使用主键所有列进行查询时是什么样子的?

innodb中怎么实现一个存储引擎锁

root@localhost : (none) 05:08:52> 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 | 2125:1062 | 2125 | 68 | 44 | test | t3 | NULL | NULL | NULL | 139846618228824 | TABLE | IX | GRANTED | NULL |
| INNODB | 2125:5:4:4 | 2125 | 68 | 44 | test | t3 | NULL | NULL | PRIMARY | 139846618225784 | RECORD | X | GRANTED | 4, 3 |
+--------+----------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+-----------+-------------+-----------+
2 rows in set (0.00 sec)

可以看到当我们使用主键的所有列进行查询时Next_Key Lock 降级为Record Lock 。

  • 场景二:RR隔离级别下对一张只有非唯一索引的表做操作 
    在RR隔离级别下,当表中只有一个索引并且为非唯一索引条件上进行等值当前读或者范围当前读时,其加锁是怎样的?

admin@localhost : test 03:55:34> set session transaction_isolation='REPEATABLE-READ' ;
Query OK, 0 rows affected (0.00 sec)
admin@localhost : test 03:29:44> show variables like '%lation';
+---------------+-----------------+
| Variable_name | Value          |
+---------------+-----------------+
| transaction_isolation| REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.01 sec)
root@localhost : test1 12:12:40> select * from t;
+------+------+
| id | xid |
+------+------+
| 1 | 1 |
| 2 | 1 |
| 4 | 3 |
| 7 | 7 |
| 10 | 9 |
+------+------+
5 rows in set (0.00 sec)
root@localhost : test1 12:08:24> show index from t;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| t3 | 1 | xid | 1 | xid | A | 3 | NULL | NULL | YES | BTREE | | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)
  • 等值当前读


innodb中怎么实现一个存储引擎锁

root@localhost : (none) 06:51:25> 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 | 1622:1059 | 1622 | 64 | 86 | test | t | NULL | NULL | NULL | 140152030668888 | TABLE | IX | GRANTED | NULL |
| INNODB | 1622:2:5:5 | 1622 | 64 | 86 | test | t | NULL | NULL | xid | 140152030665848 | RECORD | X,GAP | WAITING | 7, 0x000000000203 |
| INNODB | 1621:1059 | 1621 | 63 | 111 | test | t | NULL | NULL | NULL | 140152030662936 | TABLE | IX | GRANTED | NULL |
| INNODB | 1621:2:5:4 | 1621 | 63 | 111 | test | t | NULL | NULL | xid | 140152030659896 | RECORD | X | GRANTED | 3, 0x000000000202 |
| INNODB | 1621:2:4:4 | 1621 | 63 | 111 | test | t | NULL | NULL | GEN_CLUST_INDEX | 140152030660240 | RECORD | X | GRANTED | 0x000000000202 |
| INNODB | 1621:2:5:5 | 1621 | 63 | 111 | test | t | NULL | NULL | xid | 140152030660584 | RECORD | X,GAP | GRANTED | 7, 0x000000000203 |
+--------+----------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+-----------------+-----------------------+-----------+-----------+-------------+-------------------+
6 rows in set (0.00 sec)

事务A造成的锁

| INNODB | 1621:1059 | 1621 | 63 | 111 | test | t | NULL | NULL | NULL | 140152030662936 | TABLE | IX | GRANTED | NULL |
| INNODB | 1621:2:5:4 | 1621 | 63 | 111 | test | t | NULL | NULL | xid | 140152030659896 | RECORD | X | GRANTED | 3, 0x000000000202 |
| INNODB | 1621:2:4:4 | 1621 | 63 | 111 | test | t | NULL | NULL | GEN_CLUST_INDEX | 140152030660240 | RECORD | X | GRANTED | 0x000000000202 |
| INNODB | 1621:2:5:5 | 1621 | 63 | 111 | test | t | NULL | NULL | xid | 140152030660584 | RECORD | X,GAP | GRANTED | 7, 0x000000000203 |

事务B造成的锁

| INNODB | 1622:1059 | 1622 | 64 | 86 | test | t | NULL | NULL | NULL | 140152030668888 | TABLE | IX | GRANTED | NULL |
| INNODB | 1622:2:5:5 | 1622 | 64 | 86 | test | t | NULL | NULL | xid | 140152030665848 | RECORD | X,GAP | WAITING | 7, 0x000000000203 |
由于事务A在辅助索引记录 (3,7)之间是间隙锁,而事务B插入的数据(id,xid) ===>(5,5) 中的xid=5在(3,7) 间隙锁范围中,所以才会显示LOCK_MODE =X,GAP   LOCK_STATUS=WAITING      LOCK_DATA = 7, 0x000000000203   会等待事务A将锁释放直至超时。

事务C说明事务A造成的间隙锁实际上并没有将辅助索引记录xid=7也锁住,不包含记录xid=7。

事务A的加锁方式下图所示:

innodb中怎么实现一个存储引擎锁

  • 范围当前读

innodb中怎么实现一个存储引擎锁

root@localhost : (none) 07:08:05> 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 | 1624:1059 | 1624 | 64 | 93 | test | t | NULL | NULL | NULL | 140152030668888 | TABLE | IX | GRANTED | NULL |
| INNODB | 1624:2:5:5 | 1624 | 64 | 93 | test | t | NULL | NULL | xid | 140152030665848 | RECORD | X | WAITING | 7, 0x000000000203 |
| INNODB | 1623:1059 | 1623 | 63 | 115 | test | t | NULL | NULL | NULL | 140152030662936 | TABLE | IX | GRANTED | NULL |
| INNODB | 1623:2:5:4 | 1623 | 63 | 115 | test | t | NULL | NULL | xid | 140152030659896 | RECORD | X | GRANTED | 3, 0x000000000202 |
| INNODB | 1623:2:5:5 | 1623 | 63 | 115 | test | t | NULL | NULL | xid | 140152030659896 | RECORD | X | GRANTED | 7, 0x000000000203 |
| INNODB | 1623:2:4:4 | 1623 | 63 | 115 | test | t | NULL | NULL | GEN_CLUST_INDEX | 140152030660240 | RECORD | X | GRANTED | 0x000000000202 |
+--------+----------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+-----------------+-----------------------+-----------+-----------+-------------+-------------------+
6 rows in set (0.00 sec)

事务A 造成的锁

1、| INNODB | 1623:1059 | 1623 | 63 | 115 | test | t | NULL | NULL | NULL | 140152030662936 | TABLE | IX | GRANTED | NULL |
2、| INNODB | 1623:2:5:4 | 1623 | 63 | 115 | test | t | NULL | NULL | xid | 140152030659896 | RECORD | X | GRANTED | 3, 0x000000000202 |
3、| INNODB | 1623:2:5:5 | 1623 | 63 | 115 | test | t | NULL | NULL | xid | 140152030659896 | RECORD | X | GRANTED | 7, 0x000000000203 |
与 select * from t where xid=3 for update; 当前读相比通过mysql 8.0的performance_schema.data_locks表可以看到辅助索引记录xid=7 的LOCK_MODE =X,GAP  其不会锁定辅助索引xid=7记录,而范围当前读会将其锁住
4、| INNODB | 1623:2:4:4 | 1623 | 63 | 115 | test | t | NULL | NULL | GEN_CLUST_INDEX | 140152030660240 | RECORD | X | GRANTED | 0x000000000202 |
。

innodb中怎么实现一个存储引擎锁

  • 如果是select * from t where xid>1 and xid<=7 for update; 又是怎么样的呢?

innodb中怎么实现一个存储引擎锁

root@localhost : (none) 09:49:17> 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 | 2061:1059 | 2061 | 64 | 24 | test | t | NULL | NULL | NULL | 139846618228824 | TABLE | IX | GRANTED | NULL |
| INNODB | 2061:2:5:4 | 2061 | 64 | 24 | test | t | NULL | NULL | xid | 139846618225784 | RECORD | X | GRANTED | 3, 0x000000000202 |
| INNODB | 2061:2:5:5 | 2061 | 64 | 24 | test | t | NULL | NULL | xid | 139846618225784 | RECORD | X | GRANTED | 7, 0x000000000203 |
| INNODB | 2061:2:5:6 | 2061 | 64 | 24 | test | t | NULL | NULL | xid | 139846618225784 | RECORD | X | GRANTED | 9, 0x000000000205 |
| INNODB | 2061:2:4:4 | 2061 | 64 | 24 | test | t | NULL | NULL | GEN_CLUST_INDEX | 139846618226128 | RECORD | X | GRANTED | 0x000000000202 |
| INNODB | 2061:2:4:5 | 2061 | 64 | 24 | test | t | NULL | NULL | GEN_CLUST_INDEX | 139846618226128 | RECORD | X | GRANTED | 0x000000000203 |
+--------+----------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+-----------------+-----------------------+-----------+-----------+-------------+-------------------+
6 rows in set (0.62 sec)

其加锁下图所示: 

innodb中怎么实现一个存储引擎锁

说明:由于该表没有主键只有一个非唯一的辅助索引key(xid ),使用6字节rowid做聚集索引。

innodb中怎么实现一个存储引擎锁

  • 如果是select * from t where xid>3 for update; 又是怎么样的呢?

innodb中怎么实现一个存储引擎锁

root@localhost : test 03:25:06> 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 | 2100:1059 | 2100 | 65 | 46 | test | t | NULL | NULL | NULL | 139846618246760 | TABLE | IX | GRANTED | NULL |
| INNODB | 2100:2:5:1 | 2100 | 65 | 46 | test | t | NULL | NULL | xid | 139846618243720 | RECORD | X | WAITING | supremum pseudo-record |
| INNODB | 2099:1059 | 2099 | 67 | 28 | test | t | NULL | NULL | NULL | 139846618240760 | TABLE | IX | GRANTED | NULL |
| INNODB | 2099:2:5:6 | 2099 | 67 | 28 | test | t | NULL | NULL | xid | 139846618237880 | RECORD | X,GAP | WAITING | 9, 0x000000000205 |
| INNODB | 2098:1059 | 2098 | 66 | 40 | test | t | NULL | NULL | NULL | 139846618234776 | TABLE | IX | GRANTED | NULL |
| INNODB | 2098:2:5:5 | 2098 | 66 | 40 | test | t | NULL | NULL | xid | 139846618231848 | RECORD | X,GAP | WAITING | 7, 0x000000000203 |
| INNODB | 2097:1059 | 2097 | 64 | 75 | test | t | NULL | NULL | NULL | 139846618228824 | TABLE | IX | GRANTED | NULL |
| INNODB | 2097:2:5:1 | 2097 | 64 | 75 | test | t | NULL | NULL | xid | 139846618225784 | RECORD | X | GRANTED | supremum pseudo-record |
| INNODB | 2097:2:5:5 | 2097 | 64 | 75 | test | t | NULL | NULL | xid | 139846618225784 | RECORD | X | GRANTED | 7, 0x000000000203 |
| INNODB | 2097:2:5:6 | 2097 | 64 | 75 | test | t | NULL | NULL | xid | 139846618225784 | RECORD | X | GRANTED | 9, 0x000000000205 |
| INNODB | 2097:2:4:5 | 2097 | 64 | 75 | test | t | NULL | NULL | GEN_CLUST_INDEX | 139846618226128 | RECORD | X | GRANTED | 0x000000000203 |
| INNODB | 2097:2:4:6 | 2097 | 64 | 75 | test | t | NULL | NULL | GEN_CLUST_INDEX | 139846618226128 | RECORD | X | GRANTED | 0x000000000205 |
+--------+----------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+-----------------+-----------------------+-----------+-----------+-------------+------------------------+
12 rows in set (0.00 sec)

事务A造成的锁

| INNODB | 2097:1059 | 2097 | 64 | 75 | test | t | NULL | NULL | NULL | 139846618228824 | TABLE | IX | GRANTED | NULL |
| INNODB | 2097:2:5:1 | 2097 | 64 | 75 | test | t | NULL | NULL | xid | 139846618225784 | RECORD | X | GRANTED | supremum pseudo-record |
这里可以看到与之前的不同,上确界添加了X锁,由于使用 select * from t where xid>3 for update; 该表的xid的上确界为9,它需要将9到正无穷也要锁住,supremum pseudo-record 上确界伪记录
| INNODB | 2097:2:5:5 | 2097 | 64 | 75 | test | t | NULL | NULL | xid | 139846618225784 | RECORD | X | GRANTED | 7, 0x000000000203 |
| INNODB | 2097:2:5:6 | 2097 | 64 | 75 | test | t | NULL | NULL | xid | 139846618225784 | RECORD | X | GRANTED | 9, 0x000000000205 |
| INNODB | 2097:2:4:5 | 2097 | 64 | 75 | test | t | NULL | NULL | GEN_CLUST_INDEX | 139846618226128 | RECORD | X | GRANTED | 0x000000000203 |
| INNODB | 2097:2:4:6 | 2097 | 64 | 75 | test | t | NULL | NULL | GEN_CLUST_INDEX | 139846618226128 | RECORD | X | GRANTED | 0x000000000205 |

下图所示: 

innodb中怎么实现一个存储引擎锁

在RR隔离级别下,对一张只有非唯一辅助索引等值当前读和范围当前读造成的锁,以t表为例。

innodb中怎么实现一个存储引擎锁

  • 我们可以得出以下结论: 
    在RR隔离级别下,如果表中只有一个非唯一的辅助索引,当进行等值当前读时会与下一行记录形成间隙锁,但不会锁住下一行记录;范围当前读时会与下一行记录形成间隙锁并且会锁住该行。

    • 那么可能有人会问在RR隔离级别下,为什么在对辅助索引做范围当前读时会与下一行记录形成间隙锁并且还会锁住该行呢? 
      因为对于非唯一的辅助索引不能保证键值的唯一,所以需要锁住满足条件的下一行进行判断,当然这里还有查询优化器的功劳。

  • 场景三:RR隔离级别下对一张有主键和辅助索引的表做操作

root@localhost : test 10:20:09> select * from t2;
+----+------+
| id | xid |
+----+------+
| 1 | 1 |
| 2 | 1 |
| 4 | 3 |
| 7 | 7 |
| 10 | 9 |
+----+------+
5 rows in set (0.00 sec)
root@localhost : test 10:20:02> show index from t2;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+
| t2 | 0 | PRIMARY | 1 | id | A | 5 | NULL | NULL | | BTREE | | | YES |
| t2 | 1 | xid | 1 | xid | A | 4 | NULL | NULL | YES | BTREE | | | YES |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+
2 rows in set (0.04 sec)
  • 等值当前读

innodb中怎么实现一个存储引擎锁

root@localhost : (none) 10:29:14> 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 | 2070:1061 | 2070 | 65 | 14 | test | t2 | NULL | NULL | NULL | 139846618246760 | TABLE | IX | GRANTED | NULL |
| INNODB | 2070:4:4:5 | 2070 | 65 | 14 | test | t2 | NULL | NULL | PRIMARY | 139846618243720 | RECORD | X | GRANTED | 7 |
| INNODB | 2069:1061 | 2069 | 67 | 18 | test | t2 | NULL | NULL | NULL | 139846618240760 | TABLE | IX | GRANTED | NULL |
| INNODB | 2069:4:5:5 | 2069 | 67 | 18 | test | t2 | NULL | NULL | xid | 139846618237880 | RECORD | X,GAP | WAITING | 7, 7 |
| INNODB | 2068:1061 | 2068 | 66 | 22 | test | t2 | NULL | NULL | NULL | 139846618234776 | TABLE | IX | GRANTED | NULL |
| INNODB | 2068:4:5:4 | 2068 | 66 | 22 | test | t2 | NULL | NULL | xid | 139846618231848 | RECORD | X,GAP | WAITING | 3, 4 |
| INNODB | 2065:1061 | 2065 | 64 | 43 | test | t2 | NULL | NULL | NULL | 139846618228824 | TABLE | IX | GRANTED | NULL |
| INNODB | 2065:4:5:4 | 2065 | 64 | 43 | test | t2 | NULL | NULL | xid | 139846618225784 | RECORD | X | GRANTED | 3, 4 |
| INNODB | 2065:4:4:4 | 2065 | 64 | 43 | test | t2 | NULL | NULL | PRIMARY | 139846618226128 | RECORD | X | GRANTED | 4 |
| INNODB | 2065:4:5:5 | 2065 | 64 | 43 | test | t2 | NULL | NULL | xid | 139846618226472 | RECORD | X,GAP | GRANTED | 7, 7 |
+--------+----------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+-----------+-------------+-----------+
10 rows in set (0.01 sec)

事务A造成的锁下图所示:

| INNODB | 2065:1061 | 2065 | 64 | 43 | test | t2 | NULL | NULL | NULL | 139846618228824 | TABLE | IX | GRANTED | NULL |
| INNODB | 2065:4:5:4 | 2065 | 64 | 43 | test | t2 | NULL | NULL | xid | 139846618225784 | RECORD | X | GRANTED | 3, 4 |
| INNODB | 2065:4:4:4 | 2065 | 64 | 43 | test | t2 | NULL | NULL | PRIMARY | 139846618226128 | RECORD | X | GRANTED | 4 |
| INNODB | 2065:4:5:5 | 2065 | 64 | 43 | test | t2 | NULL | NULL | xid | 139846618226472 | RECORD | X,GAP | GRANTED | 7, 7 |

innodb中怎么实现一个存储引擎锁

innodb中怎么实现一个存储引擎锁

分析:在RR隔离级别下,一张带有主键和非唯一的辅助索引表,使用辅助索引进行当前读时与只有非唯一的辅助索引表进行等值当前读时,都不会将辅助索引的下一行记录进行加锁,只会将下一行记录与前一行记录添加间隙锁。

  • 范围当前读

innodb中怎么实现一个存储引擎锁

事务A的造成的锁:

root@localhost : test 11:07:47> 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 | 2086:1061 | 2086 | 64 | 52 | test | t2 | NULL | NULL | NULL | 139846618228824 | TABLE | IX | GRANTED | NULL |
| INNODB | 2086:4:5:4 | 2086 | 64 | 52 | test | t2 | NULL | NULL | xid | 139846618225784 | RECORD | X | GRANTED | 3, 4 |
| INNODB | 2086:4:5:5 | 2086 | 64 | 52 | test | t2 | NULL | NULL | xid | 139846618225784 | RECORD | X | GRANTED | 7, 7 |
| INNODB | 2086:4:5:6 | 2086 | 64 | 52 | test | t2 | NULL | NULL | xid | 139846618225784 | RECORD | X | GRANTED | 9, 10 |
| INNODB | 2086:4:4:4 | 2086 | 64 | 52 | test | t2 | NULL | NULL | PRIMARY | 139846618226128 | RECORD | X | GRANTED | 4 |
| INNODB | 2086:4:4:5 | 2086 | 64 | 52 | test | t2 | NULL | NULL | PRIMARY | 139846618226128 | RECORD | X | GRANTED | 7 |
| INNODB | 2086:4:4:6 | 2086 | 64 | 52 | test | t2 | NULL | NULL | PRIMARY | 139846618226128 | RECORD | X | GRANTED | 10 |
+--------+----------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+-----------+-------------+-----------+
7 rows in set (0.00 sec)

innodb中怎么实现一个存储引擎锁

innodb中怎么实现一个存储引擎锁

总结

综上所述,在RR隔离级别下的加锁方式:

innodb中怎么实现一个存储引擎锁

说明:对于唯一键值的锁定,next_key lock 降级为 Record lock 仅存在于查询所有的唯一索引列。如果唯一索引有多个列组成,而查询仅是多个唯一索引列中的一个,那么查询其实是rang类型的查询,而不是point类型的查询,故innodb存储引擎依然使用next_key lock进行锁定。

innodb中怎么实现一个存储引擎锁

上述内容就是innodb中怎么实现一个存储引擎锁,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程网数据库频道。

您可能感兴趣的文档:

--结束END--

本文标题: innodb中怎么实现一个存储引擎锁

本文链接: https://www.lsjlt.com/news/58624.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • innodb中怎么实现一个存储引擎锁
    本篇文章为大家展示了innodb中怎么实现一个存储引擎锁,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。| innodb存储引擎行锁的算法数据库对锁的使用是...
    99+
    2022-10-18
  • Innodb中怎么查询存储引擎查
    本篇文章给大家分享的是有关Innodb中怎么查询存储引擎查,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。源码分析查询于存储引擎的实现密切相关,...
    99+
    2022-10-18
  • 详解MySql中InnoDB存储引擎中的各种锁
    目录什么是锁InnoDB存储引擎中的锁锁的算法行锁的3种算法幻像问题锁的问题脏读不可重复读丢失更新死锁什么是锁 现实生活中的锁是为了保护你的私有物品,在数据库中锁是为了解决资源争抢的...
    99+
    2022-11-13
  • MySQL中InnoDB存储引擎是什么
    这篇文章给大家分享的是有关MySQL中InnoDB存储引擎是什么的内容。小编觉得挺实用的,因此分享给大家做个参考。一起跟随小编过来看看吧。在MySQL中InnoDB属于存储引擎层,并以插件的形式集成在数据库...
    99+
    2022-10-18
  • MySQL 存储引擎 - InnoDB 实现原理介绍
    存储结构   内存结构 内存结构主要包括 Buffer Pool、Change Buffer、Adaptive Hash Index和 Log Buffer 四大组件 Buffer Pool 缓冲池,简称BP。BP以 Page 页为单位,...
    99+
    2023-10-04
    mysql 数据库
  • mysql innodb存储引擎中一个事务的完整流程分析
    这篇文章主要讲解了“mysql innodb存储引擎中一个事务的完整流程分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“mysql innodb存储引擎中...
    99+
    2022-10-19
  • 总结mysql5.7中innodb存储引擎的一些知识
    本文主要给大家简单讲讲mysql5.7中innodb存储引擎的一些知识,相关专业术语大家可以上网查查或者找一些相关书籍补充一下,这里就不涉猎了,我们就直奔主题吧,希望mysql5.7中innodb存储引擎的...
    99+
    2022-10-18
  • mysql中InnoDB存储引擎指的是什么
    这篇文章主要介绍了mysql中InnoDB存储引擎指的是什么,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。mysql中InnoDB存储引擎1、说明MySQL默认事务型存储引擎...
    99+
    2023-06-15
  • innodb存储引擎备份工具Xtrabackup怎么用
    这篇文章主要介绍innodb存储引擎备份工具Xtrabackup怎么用,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完! 首先提一下还有一个备份工具是ibba...
    99+
    2022-10-18
  • MySQL学习(七):Innodb存储引擎索引的实现原理
    概述 在数据库当中,索引就跟树的目录一样用来加快数据的查找速度,对于一个SQL查询操作,根据索引快速过滤掉不符合要求的数据并定位到符合要求的数据,从而不需要扫描整个表来获取所需的数据。在innodb存储引擎...
    99+
    2022-10-18
  • 如何进行MySQL INNODB存储引擎中各类型SQL加锁分析
    这篇文章给大家介绍如何进行MySQL INNODB存储引擎中各类型SQL加锁分析,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。 MYSQL5.6事物隔离级...
    99+
    2022-10-19
  • 基于xtrabackup来实现InnoDB存储引擎的备份恢复
             在InnoDB存储引擎中,xtrabackup能够完全以热备的形式进行,实现快速可靠地完全备份和部分备份,支持增量备份,支持时间点还原,备份过程中不会打扰到事务操作,压缩功能有效的节约磁盘...
    99+
    2022-10-18
  • MySQL中怎么实现一个搜索引擎
    本篇文章为大家展示了MySQL中怎么实现一个搜索引擎,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。前言 只有Innodb和myisam存储引擎能用全文索引...
    99+
    2022-10-18
  • 怎么用JavaScript实现一个模板引擎
    这篇文章给大家分享的是有关怎么用JavaScript实现一个模板引擎的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。功能分析一个模板引擎,在我看来,就是由两块核心功能组成,一个是用...
    99+
    2022-10-19
  • PHP中怎么实现一个站内搜索引擎
    这篇文章将为大家详细讲解有关PHP中怎么实现一个站内搜索引擎,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。PHP实现站内搜索引擎的具体代码:<   inc...
    99+
    2023-06-17
  • MySQL中怎么设置存储引擎
    今天就跟大家聊聊有关MySQL中怎么设置存储引擎,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。MySQL设置存储引擎 1)查询存储引擎l ...
    99+
    2022-10-18
  • javascript中怎么实现一个基于DOM的模板引擎
    本篇内容主要讲解“javascript中怎么实现一个基于DOM的模板引擎”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“javascript中怎么实现一个基于DO...
    99+
    2022-10-19
  • MySQL中innodb行锁怎么实现
    在MySQL中,InnoDB引擎通过使用锁来实现行级锁。行锁可以通过以下几种方式来实现:1. 自动行锁:InnoDB引擎会根据需要自...
    99+
    2023-10-09
    MySQL
  • Mysql中怎么实现 InnoDB行锁
    Mysql中怎么实现 InnoDB行锁,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Mysql InnoDB行锁实现方式&nb...
    99+
    2022-10-18
  • mysql中怎么修改默认存储引擎
    mysql中怎么修改默认存储引擎,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。修改mysql的默认存储引擎 1、查看mysql存储引...
    99+
    2022-10-18
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作