上一篇文章我们提到MySQL InnoDB对数据行的锁定类型一共有四种:共享锁(读锁,S锁)、排他锁(写锁,X锁)、意向共享锁(IS锁)和意向排他锁(IX锁),今天我们要讨论的是MySQL InnoDB对数据行的锁定方式。
MySQL InnoDB支持三种行锁定方式:
- 行锁(Record Lock):锁直接加在索引记录上面。
- 间隙锁(Gap Lock):锁加在不存在的空闲空间,可以是两个索引记录之间,也可能是第一个索引记录之前或最后一个索引之后的空间。
- Next-Key Lock:行锁与间隙锁组合起来用就叫做Next-Key Lock。
默认情况下,InnoDB工作在可重复读隔离级别下,并且以Next-Key Lock的方式对数据行进行加锁,这样可以有效防止幻读的发生。Next-Key Lock是行锁与间隙锁的组合,这样,当InnoDB扫描索引记录的时候,会首先对选中的索引记录加上行锁(Record Lock),再对索引记录两边的间隙加上间隙锁(Gap Lock)。如果一个间隙被事务T1加了锁,其它事务是不能在这个间隙插入记录的。
我们来看看例子,首先建一张表。
CREATE TABLE tb1 ( id int(11) NOT NULL, id2 int(11) NOT NULL, PRIMARY KEY (id), KEY idx (id2) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
创建一些记录。
insert into tb1 values(1, 3), (2, 6), (3, 9);
tb1表现在有3条记录,其中普通索引字段id2的值3、6、9把间隙分成了四份:(-,3)、(3、6)、(6、9)、(9、+)。现在我们看看基于id2 = 6加锁的情况,会话S1中对id2 = 6的记录加S锁。
mysql> start transaction; Query OK, 0 rows affected (0.00 sec) mysql> select * from tb1 where id2 = 6 lock in share mode; +----+-----+ | id | id2 | +----+-----+ | 2 | 6 | +----+-----+ 1 row in set (0.00 sec) mysql>
会话S2中尝试插入id2 = 5或id2 = 7的记录。
mysql> start transaction; Query OK, 0 rows affected (0.00 sec) mysql> insert into tb1 values(4, 5); ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction mysql> insert into tb1 values(4, 7); ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction mysql>
从结果可知,会话2发生了锁等待超时,因为会话S1中的事务锁住了这些空隙(3、6)与(6、9)。如果插入的记录是id2 = 1或id2 = 10,那就不会有问题,因为这些间隙没有被任何事务锁住,如:
mysql> start transaction; Query OK, 0 rows affected (0.00 sec) mysql> insert into tb1 values(4, 5); ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction mysql> insert into tb1 values(4, 7); ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction mysql> insert into tb1 values(4, 2); Query OK, 1 row affected (0.00 sec) mysql> insert into tb1 values(5, 10); Query OK, 1 row affected (0.00 sec) mysql>
间隙锁在InnoDB的唯一作用就是防止其它事务的插入操作,以此来达到防止幻读的发生,所以间隙锁不分什么共享锁与排它锁。另外,在上面的例子中,我们选择的是一个普通(非唯一)索引字段来测试的,这不是随便选的,因为如果InnoDB扫描的是一个主键、或是一个唯一索引的话,那InnoDB只会采用行锁方式来加锁,而不会使用Next-Key Lock的方式,也就是说不会对索引之间的间隙加锁,仔细想想的话,这个并不难理解,大家也可以自己测试一下。
要禁止间隙锁的话,可以把隔离级别降为读已提交,或者开启参数innodb_locks_unsafe_for_binlog。
相关推荐
#### 三、InnoDB锁机制 **1、事务基础概念** 事务是数据库操作的基本单位,确保数据的一致性和完整性。InnoDB支持ACID特性(原子性、一致性、隔离性、持久性),并通过多种锁机制来实现这些特性。 **2、锁机制...
MySQL 8.0 锁机制和事务 MySQL 8.0 中的锁机制和事务是数据库系统中非常重要的概念。锁机制是指数据库系统中对数据访问的控制机制,而事务是指数据库系统中的一组操作单元。了解锁机制和事务是非常关键的,因为它们...
MySQL的引擎简介,InnoDB的锁机制与事务隔离级别
MySQL的锁机制是数据库管理系统中用于控制并发操作的重要机制,对于多用户环境下的数据一致性、事务隔离性和系统性能有着至关重要的影响。本文将深入探讨MySQL的高级锁机制,包括表锁和行锁,并提供一些优化建议。 ...
在MySQL的InnoDB存储引擎中,插入操作不仅涉及到行级锁,还可能涉及Gap锁和Next-Key Locks,这些锁机制的设计是为了防止幻读(Phantom Read)和其他并发问题。 1. 数据库版本:文中提到的是MySQL 5.6.27。不同版本...
MySQL的锁机制是数据库管理系统中用于控制并发操作的重要机制,对于保证数据的一致性和完整性起着至关重要的作用。本文将深入解析MySQL中的锁机制,帮助读者理解其工作原理,为面试准备或日常数据库管理提供有力支持...
关于mysql中的innodb存储引擎的索引机制简介,详细介绍了锁机制
在MySQL中,锁机制是保障数据操作安全的重要组成部分,其主要分为表锁、行锁和间隙锁。本知识点详细解读了MySQL锁机制的定义、分类、特点以及具体的应用案例。 1. 锁的定义和分类 在数据库系统中,锁是用来控制多...
### MySQL锁机制详解 #### 一、MySQL锁机制概述 MySQL中的锁机制是数据库管理系统用于控制并发事务对数据资源访问的关键技术之一。合理地管理和利用锁机制能够有效地防止数据不一致性和提高系统的并发处理能力。...
MySQL锁机制是数据库管理系统中用于协调多个事务或者进程,以保证数据的完整性和一致性的一套规则。在数据库操作中,保证数据并发访问时的一致性、有效性是至关重要的,锁机制正是为此而生。 MySQL支持不同存储引擎...
### MySQL 5.6 新特性-InnoDB:深入剖析 #### MySQL 5.6 版本简介及重要性 MySQL 5.6 是 MySQL 的一个重要版本,相比于之前的版本(如 MySQL 5.1 和 5.5),它在多个方面进行了显著的改进。这些改进不仅提升了...
深入学习《MySQL内核:InnoDB存储引擎 卷1》,读者可以了解到InnoDB的内部工作机制,如如何处理B+树索引、事务的提交与回滚、锁的实现以及内存管理等内容,这对于优化数据库性能、解决并发问题、设计高效的数据模型...
内容深入,从源代码的角度深度解析了InnoDB的体系结构、实现原理、工作机制,并给出了大量最佳实践,能帮助你系统而深入地掌握InnoDB,更重要的是,它能为你设计和管理高性能、高可用的数据库系统提供绝佳的指导。...
卷1》由资深MySQL专家,机工畅销图书作者亲自执笔,在以往出版的两本InnoDB介绍性图书的基础之上,更深入地介绍InnoDB存储引擎的内核,例如latch、B+树索引、事务、锁等,从源代码的角度深度解析了InnoDB的体系结构...