Mysql中有哪些锁
按锁的粒度划分
锁的粒度决定了锁会影响的数据范围,粒度越小,并发度越高,但系统开销也越大。
1. 全局锁 (Global Lock)
- 作用:对整个数据库实例加锁。最典型的命令是
FLUSH TABLES WITH READ LOCK(FTWRL)。 - 效果:当执行这个命令后,整个数据库就处于只读状态。所有的数据更新语句(DML)和数据定义语句(DDL)都会被阻塞。
- 使用场景:主要用于做全库的逻辑备份(比如使用
mysqldump),以保证在备份期间数据的一致性,不会有新的修改写入。
2. 表级锁 (Table-level Lock)
- 作用:直接锁定一整张表。这是MySQL中最基本的锁策略,开销小,加锁快,但并发度最低。
- 主要类型:
- 表读锁(Read Lock):也叫共享锁。一个事务对表加了读锁后,其他事务也可以对该表加读锁,但不能加写锁。
- 表写锁(Write Lock):也叫排他锁。一个事务对表加了写锁后,其他事务既不能加读锁,也不能加写锁。
- 引擎实现:MyISAM存储引擎主要使用的就是表级锁。InnoDB在执行某些DDL语句时(如
ALTER TABLE)也会使用表级锁。 - InnoDB中的意向锁:InnoDB为了支持多粒度锁定(即允许表锁和行锁共存),引入了意向锁。意向锁本身也是一种表级锁,它分为:
- 意向共享锁(IS):表示一个事务准备在表中的某些行上加共享锁(S锁)。
- 意向排他锁(IX):表示一个事务准备在表中的某些行上加排他锁(X锁)。 意向锁是由引擎自动管理的,不需要用户干预。它的作用是,当一个事务想对整张表加表锁时,只需要检查该表是否有意向锁,就可以快速判断是否需要等待,而不用去逐行检查是否有行锁。
3. 行级锁 (Row-level Lock)
- 作用:锁定某一行或多行数据。这是InnoDB存储引擎的巨大优势所在。它锁定的粒度最细,并发冲突最小,能够支持最大的并发度。
- 实现:InnoDB的行级锁是基于索引来实现的。如果一条SQL语句没有使用到索引,那么行级锁可能会退化为表级锁。
- 主要类型(InnoDB):
- 记录锁 (Record Lock):这是最简单的行锁,它精确地锁定一条索引记录。
- 间隙锁 (Gap Lock):它锁定的是一个索引记录之间的“间隙”,不包含记录本身。比如锁定
(3, 5)这个开区间。它的主要作用是防止其他事务在这个间隙中插入新的记录,从而解决了幻读问题。 - 临键锁 (Next-Key Lock):这是记录锁和间隙锁的结合体,它锁定一个索引记录以及该记录前面的那个间ഗ്യ。比如锁定
(3, 5]这个左开右闭区间。这是InnoDB在可重复读隔离级别下,行级锁的默认算法。
按锁的模式划分
这个维度描述的是锁与锁之间的关系。
1. 共享锁 (Shared Lock / S Lock)
- 也称为读锁。
- 特点:多个事务可以同时对同一份数据持有共享锁。一个事务持有S锁时,其他事务可以再申请S锁,但不能申请X锁。
- 用法:在普通
SELECT语句后加上LOCK IN SHARE MODE。 - 通俗比喻:大家可以一起读书,但有人在读书时,不允许任何人来撕书或改写内容。
2. 排他锁 (Exclusive Lock / X Lock)
- 也称为写锁。
- 特点:排他锁是独占的。一旦一个事务对某份数据持有了排他锁,其他任何事务都不能再对这份数据加任何类型的锁(无论是S锁还是X锁),直到持有者释放它。
- 用法:
INSERT,UPDATE,DELETE这些写操作会自动加上排他锁。也可以在SELECT语句后加上FOR UPDATE来手动加排他锁。 - 通俗比喻:一个人在修改文件时,不允许任何人来看,也不允许任何人来修改。
| 维度 | 类型 | 解释 |
|---|---|---|
| 粒度 | 全局锁 | 锁定整个数据库实例,用于备份。 |
| 表级锁 | 锁定整张表,MyISAM主要使用。InnoDB有表锁和更重要的意向锁。 | |
| 行级锁 | 锁定单行或多行,InnoDB核心优势。包括记录锁、间隙锁、临键锁。 | |
| 模式 | 共享锁 (S Lock) | 读锁,允许多个读事务共存,但与写事务互斥。 |
| 排他锁 (X Lock) | 写锁,完全独占,与任何其他锁都互斥。 |