全局锁
全局锁是对整个数据库实例加锁,加锁后整个库处于只读状态。
- 加锁后,所有写操作(DML)和结构变更(DDL)被阻塞
- 但读操作(DQL)仍可正常执行
- 是 MySQL 中粒度最大的锁
加全局读锁
flush tables with read lock;
执行后,其他线程的以下操作会被阻塞:
- DML 写操作:
INSERT、UPDATE、DELETE - DDL 操作:
CREATE、ALTER、DROP - 更新类事务的提交
而 SELECT 等读操作不受影响。
释放全局锁
unlock tables;
会话断开时,全局锁会自动释放。
权限要求
执行 flush tables with read lock 需要 reload 权限。
表锁
表锁是对整张表加锁,锁定后其他会话对该表的读写会受到限制。
- 粒度:表级(比行锁大,比全局锁小)
- 引擎:MyISAM、MEMORY 默认使用表锁;InnoDB 也支持表锁
- 开销小、加锁快,但并发度低
- 不会出现死锁(因为一次性锁定整表)
加表锁
-- 加读锁 阻塞自己和其他人的写
lock tables 表名 read;
-- 加写锁 阻塞其他人的读写
lock tables 表名 write;
-- 多表同时加锁
lock tables 表1 read, 表2 write;
释放表锁
unlock tables; -- 解全局锁/表锁
会话断开时,表锁自动释放。
元数据锁
元数据锁是 MySQL Server 层实现的锁机制,用于在并发环境下保护数据库对象的元数据(表结构、库结构等)不被并发修改,保证数据一致性。
- 自动加锁:不需要手动
LOCK,访问表时系统自动加 - 作用对象:表、库、存储程序、表空间等
- 核心目的:防止一个会话正在读写表时,另一个会话修改表结构
MDL 不是表锁,是保护"表定义"的锁,与 InnoDB 的行锁是两个层面的机制。
-- 查看元数据锁
select object_type,object_schema,object_name,lock_type,lock_duration from performance_schema.metadata_locks;
意向锁
意向锁是 InnoDB 存储引擎在表级别加的锁,用于标记"表中某些行即将被/已被加锁" ,是一种辅助锁。
- 由 InnoDB 自动添加,用户无法手动干预
- 不直接锁数据,只表示"有意向"
- 目的:快速判断表中是否有行锁,避免逐行检查
- 表级锁,与行锁配合使用
意向锁不是用来锁数据的,而是用来提高加表锁的效率。
select * from tb_emp where id = 1 lock in share mode; # 加共享行锁
select * from tb_emp where id = 1 for update; # 加排他行锁
-- 查看意向锁
select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_locks;
行级锁
行级锁是 InnoDB 存储引擎在索引记录上加的锁,锁定的是行数据而非整张表。
- 粒度最小:只锁涉及的行,并发度高
- 基于索引:行锁加在索引记录上,不是物理行
- 自动加锁:
UPDATE、DELETE、SELECT ... FOR UPDATE自动加 - 开销较大:相比表锁,加锁慢、内存消耗多
- 可能死锁:并发加锁顺序不一致时
select * from tb_emp where id = 1 lock in share mode; # 加共享行锁
select * from tb_emp where id = 1 for update; # 加排他行锁