MySQL进阶学习五(锁)

17 阅读3分钟

全局锁

全局锁是对整个数据库实例加锁,加锁后整个库处于只读状态

  • 加锁后,所有写操作(DML)和结构变更(DDL)被阻塞
  • 读操作(DQL)仍可正常执行
  • 是 MySQL 中粒度最大的锁

加全局读锁

flush tables with read lock;

执行后,其他线程的以下操作会被阻塞

  • DML 写操作INSERTUPDATEDELETE
  • DDL 操作CREATEALTERDROP
  • 更新类事务的提交

而 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 存储引擎索引记录上加的锁,锁定的是行数据而非整张表。

  • 粒度最小:只锁涉及的行,并发度高
  • 基于索引:行锁加在索引记录上,不是物理行
  • 自动加锁UPDATEDELETESELECT ... FOR UPDATE 自动加
  • 开销较大:相比表锁,加锁慢、内存消耗多
  • 可能死锁:并发加锁顺序不一致时
select * from tb_emp where id = 1 lock in share mode; # 加共享行锁
select * from tb_emp where id = 1  for update; # 加排他行锁