MySQL 锁机制
概述
InnoDB 共有七种类型的锁:
- 共享/排它锁(Shared and Exclusive Locks)
- 意向锁(Intention Locks)
- 记录锁(Record Locks)
- 间隙锁(Gap Locks)
- 临键锁(Next-key Locks)
- 插入意向锁(Insert Intention Locks)
- 自增锁(Auto-inc Locks)
详解
根据锁的性质来划分
共享锁(Shared)
共享锁(Share Locks,记为 S 锁),读取数据时加 S 锁。
允许事务读取(SELECT)数据,但不允许修改。多个事务可以同时持有对同一数据的共享锁,即共享锁之间是兼容的,但共享锁与排他锁不兼容。
排它锁( Exclusive Locks)
排他锁(eXclusive Locks,记为 X 锁),修改数据时加 X 锁。
不仅允许事务读取数据,还允许修改(INSERT/UPDATE/DELETE)数据。一旦一个事务对数据加了排他锁,其他任何事务都无法再对该数据加任何类型的锁,直到该排他锁被释放。排他锁与其他所有类型的锁都不兼容。
意向锁(Intention Locks)
InnoDB 为了支持多粒度锁机制(multiple granularity locking),即允许行级锁与表级锁共存,而引入了意向锁(intention locks)。意向锁是指,未来的某个时刻,事务可能要加共享/排它锁了,先提前声明一个意向。意向锁是一个表级别的锁(table-level locking)。
意向锁又分为:
- 意向共享锁(intention shared lock, IS),它预示着,事务有意向对表中的某些行加共享 S 锁。
- 意向排它锁(intention exclusive lock, IX),它预示着,事务有意向对表中的某些行加排它 X 锁。
加锁的语法为
select ... lock in share mode; 要设置IS锁;
select ... for update; 要设置IX锁;
根据锁作用的具体数据单元划分
记录锁(Record Locks)
对表中的记录加锁,叫做记录锁,简称行锁。
create table lock_example(id smallint(10),name varchar(20),primary key id)engine=innodb;
select * from t where id=1 for update;
间隙锁(Gap Locks)
间隙锁,它封锁索引记录中的间隔,或者第一条索引记录之前的范围,又或者最后一条索引记录之后的范围。
select * from lock_example where id between 8 and 15 for update;
这个 SQL 语句会封锁区间(8,15),以阻止其他事务插入 id 位于该区间的记录。
如果把事务的隔离级别降级为读提交(Read Committed, RC),间隙锁则会自动失效。
临键锁(Next-key Locks)
临键锁,是记录锁与间隙锁的组合,它的封锁范围,既包含索引记录,又包含索引区间。
Innodb 使用 next-key locks 来锁定记录。但当查询的索引含有唯一属性的时候,Next-Key Lock 会进行优化,将其降级为 Record Lock,即仅锁住索引本身,不是范围。
表锁(Table Locks)
锁定整个表,是最粗粒度的锁。虽然InnoDB主要使用行级锁,但在某些操作下(如ALTER TABLE、LOCK TABLES等)仍然会使用表锁。
特殊情况
自增锁(Auto-inc Locks)
自增锁是一种特殊的表级别锁(table-level lock),专门针对事务插入 AUTO_INCREMENT 类型的列。最简单的情况,如果一个事务正在往表中插入记录,所有其他事务的插入必须等待,以便第一个事务插入的行,是连续的主键值。
总结
MySQL的InnoDB存储引擎构建了一套精密的锁机制,巧妙地平衡了数据一致性与高并发处理的需求。这套机制依据锁的作用性质及锁定数据的精确度,细分为多种类型,确保了事务间的高效协作与数据完整性。
按性质划分:
- 共享锁,允许多个事务并行读取数据,保证读取过程中数据不被修改。
- 排他锁,为数据修改提供独占访问权,确保更新操作的原子性和一致性。
- 意向锁,作为高级锁的预告,标记事务计划在表内行上应用的锁类型,优化锁管理效率。
按数据单元划分:
- 记录锁,精准控制,锁定单个数据行,支撑行级并发控制。
- 间隙锁,守护数据顺序,锁定索引区间,防止插入幻影行,强化可重复读隔离级别。
- 临键锁,结合记录锁与间隙锁优势,全面防护,有效杜绝幻读现象。
- 表锁,在特定操作如表结构修改时使用,虽粒度较粗,但在必要时保障整体数据安全。
此外,还有针对自动增长列的自增锁,确保ID值的连续性和唯一性。