mysql 中的锁可以从锁粒度、锁类型、锁状态三个维度划分,下面按 “粒度 + 类型” 的逻辑体系,逐一说明所有核心锁的定义、作用和使用场景:
一、按锁粒度划分(核心分类)
锁粒度决定了锁的影响范围,粒度越小,并发度越高,但锁管理开销越大。
1. 全局锁
- 定义:锁定整个 mysql 实例,是粒度最大的锁。
- 作用:保证整个实例的数据一致性,防止数据被修改。
- 具体实现:
flush tables with read lock (ftwrl) - 使用场景:
- 全库逻辑备份(避免备份过程中数据被修改);
- 跨库事务一致性读取(极少用,因为会阻塞所有写操作)。
- 注意:加全局锁后,所有库的所有表都只能读,写操作(增删改、ddl)全部阻塞;解锁用
unlock tables。
2. 表级锁
锁定整张表,粒度比全局锁小,开销小、加锁快,但并发度低。mysql 中表级锁分为两类:
表格
| 锁类型 | 定义 | 作用 | 适用场景 |
|---|---|---|---|
| 表读锁(read) | 共享锁(s 锁) | 加锁后,自己和其他会话都能读表,所有会话都不能写表 | 只读操作(如批量查询) |
| 表写锁(write) | 排他锁(x 锁) | 加锁后,只有自己能读写表,其他会话既不能读也不能写 | 批量修改表数据(如全表更新) |
| 元数据锁(mdl) | 隐式加锁(无需手动) | 保护表结构(元数据)不被修改,ddl 操作会加 mdl 写锁,dml / 查询加 mdl 读锁 | 防止查询时表结构被修改 |
| 意向锁(is/ix) | 表级的 “标记锁” | 表示 “某个事务准备给表中的行加锁”,避免行锁和表锁冲突 | 配合行锁使用(自动加锁) |
1.意向共享锁(is):与表锁共享锁(read)兼容,与表锁排他锁(write)互斥。
2.意向排他锁(ix):与表锁共享锁(read)及排他锁(write)都互斥。意向锁之间不会互斥。
手动加表锁命令:
lock tables table_name read; -- 加读锁 lock tables table_name write; -- 加写锁 unlock tables; -- 解锁
3. 行级锁
锁定表中的单行数据,粒度最小,并发度最高,但加锁开销大(innodb 引擎特有,myisam 不支持)。
| 锁类型 | 定义 | 作用 |
|---|---|---|
| 行共享锁(s 锁) | 事务对行加 s 锁后,其他事务可加 s 锁(共享读),但不能加 x 锁(排他写) | 允许并发读,防止读时被修改(如select ... lock in share mode) |
| 行排他锁(x 锁) | 事务对行加 x 锁后,其他事务既不能加 s 锁也不能加 x 锁 | 保证修改 / 删除时数据独占,防止并发修改(如update/delete/insert) |
| 间隙锁(gap lock) | 锁定索引记录之间的 “间隙”(不包含记录本身),防止插入新数据 | 解决幻读问题(rr 隔离级别下自动生效) |
| 临键锁(next-key lock) | 行锁 + 间隙锁的组合,锁定 “记录 + 记录前的间隙”,是 innodb 默认的行锁方式 | 同时防止幻读、不可重复读(rr 隔离级别下核心锁) |
| 插入意向锁(insert intention lock) | 多个事务插入同一间隙时的 “意向锁”,互不阻塞 | 提升并发插入效率(如多个事务插入不同行到同一间隙) |
| 自增锁(auto-inc lock) | 针对自增列的表级锁,保证自增 id 连续唯一 | 防止自增 id 重复(可通过innodb_autoinc_lock_mode调整锁粒度) |
行锁示例:
-- 加行共享锁(s锁) select * from user where id=1 lock in share mode; -- 加行排他锁(x锁) select * from user where id=1 for update; -- 普通dml自动加x锁 update user set name='test' where id=1;
二、按锁属性补充分类
除了粒度,还可按 “锁的竞争关系” 划分:
- 共享锁(s 锁):多事务共享读权限,互斥写权限(如行 s 锁、表读锁);
- 排他锁(x 锁):独占读写权限,其他事务无法加任何锁(如行 x 锁、表写锁);
- 意向锁(is/ix):表级的 “预告锁”,is = 意向共享(准备加行 s 锁),ix = 意向排他(准备加行 x 锁),仅用于判断表锁和行锁的冲突,无需手动操作。
三、特殊场景的锁
- 页锁:锁定数据页(innodb 的存储结构,一页约 16kb),粒度介于行锁和表锁之间,mysql 极少单独使用,仅 innodb 内部优化时用到;
- 死锁:并非 “锁类型”,而是多事务互相持有对方需要的锁导致的阻塞状态,mysql 会自动检测并回滚其中一个事务解决。
总结
- 核心锁粒度:全局锁(整实例)> 表级锁(整表)> 行级锁(单行),粒度越小并发越高、开销越大;
- 核心锁类型:共享锁(s)和排他锁(x)是基础,间隙锁 / 临键锁是 innodb 解决幻读的核心,mdl 锁保护表结构;
- 引擎差异:myisam 仅支持表级锁,innodb 支持行级锁 + 表级锁,行锁是 innodb 保证事务 acid 的核心。
关键点:日常开发中,90% 的场景关注行级锁(x/s/ 临键锁) 和mdl 锁 即可,全局锁仅用于备份,表级锁尽量避免(会降低并发)。
到此这篇关于mysql 锁的完整分类与详解的文章就介绍到这了,更多相关mysql锁分类内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论