基于本文回答

播面 播面

刷题像听歌,多听自然懂
0
评论

MySQL中支持哪些粒度的锁?

知识点图片

在 MySQL 中,锁的粒度(Granularity)指的是被加锁的数据范围大小。MySQL 支持多种粒度的锁,主要取决于所使用的存储引擎以及具体的操作。

按照锁的粒度从大到小划分,MySQL 主要支持以下 4 种粒度的锁:


1. 全局锁(Global Locks)

全局锁是对整个 MySQL 数据库实例加锁。

  • 作用范围:整个数据库实例。加锁后,整个数据库处于只读状态,任何对数据的增删改(DML)、表结构更改(DDL)以及更新类事务的提交都会被阻塞。
  • 实现命令FLUSH TABLES WITH READ LOCK;(简称 FTWRL)。解锁使用 UNLOCK TABLES;
  • 主要应用场景全库逻辑备份(如使用 mysqldump)。为了保证备份时数据的一致性,防止备份过程中有数据写入。
  • 注:对于 InnoDB 引擎,由于其支持 MVCC(多版本并发控制),通常在备份时使用 --single-transaction 参数来获取一致性视图,从而避免使用全局锁,不影响业务写入。

2. 表级锁(Table-level Locks)

表级锁是对当前操作的整张表加锁。它是 MySQL Server 层和多种存储引擎(如 MyISAM、InnoDB、Memory)都支持的锁。

  • 特点:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
  • 分类
    • 普通表锁(Table Lock)
      • 读锁(共享锁):LOCK TABLES t1 READ;(阻塞写,不阻塞读)。
      • 写锁(排他锁):LOCK TABLES t1 WRITE;(阻塞读和写)。
    • 元数据锁(MDL, Metadata Lock)
      • MySQL 5.5 引入。不需要显式调用,访问表时自动加上。
      • 当你对表做 DML 操作(增删改查)时,加 MDL 读锁;对表做 DDL 操作(如改表结构、加索引)时,加 MDL 写锁。它的主要作用是防止 DDL 和 DML 并发导致的数据不一致
    • 意向锁(Intention Lock)(InnoDB 特有):
      • 分为意向共享锁(IS)和意向排他锁(IX)。
      • 它是 InnoDB 自动加的表级锁。目的是为了在加表锁时,能快速判断表里是否有记录被加了行锁,从而提高加表锁的效率。

3. 行级锁(Row-level Locks)

行级锁是对数据表中的单独一行或多行记录加锁。这是 InnoDB 存储引擎的标志性特性(MyISAM 不支持)。

  • 特点:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度最高。
  • 核心机制InnoDB 的行锁是加在「索引」上的,而不是加在物理行记录上。 如果查询没有命中索引,InnoDB 会退化为锁定表中的所有行(相当于表锁的效果)。
  • 分类(根据锁定范围不同):
    • 记录锁(Record Lock):仅仅锁住某一条索引记录。例如 WHERE id = 1 FOR UPDATE;(id 是主键或唯一索引)。
    • 间隙锁(Gap Lock):锁住两个索引记录之间的间隙,不包括记录本身。主要用于在可重复读(RR)隔离级别下解决幻读问题,防止其他事务在这个间隙插入新数据。
    • 临键锁(Next-Key Lock)记录锁 + 间隙锁的组合。既锁住当前记录,又锁住记录前面的间隙。这是 InnoDB 在可重复读(RR)隔离级别下的默认行锁算法

4. 页级锁(Page-level Locks)

页级锁是介于表锁和行锁之间的一种锁。

  • 作用范围:对一页数据(在 MySQL 中通常一页是 16KB,包含多行记录)进行加锁。
  • 特点:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
  • 支持引擎:早期 MySQL 的 BDB (Berkeley DB) 存储引擎支持页级锁,但由于 BDB 引擎目前已被弃用/移除,因此页级锁在现代 MySQL 开发中极少提及,仅作概念了解即可。

总结与对比

锁粒度 开销与加锁速度 死锁情况 并发性能 支持的存储引擎 典型应用场景
全局锁 最小,极快 不会发生 极低 Server层 全库物理/逻辑备份
表级锁 小,快 不会发生(普通表锁) MyISAM, Memory, InnoDB 整体表数据的迁移、DDL变更
页级锁 中等 会发生 中等 BDB (已弃用) 历史概念,目前较少使用
行级锁 大,慢 会发生 极高 InnoDB 高并发的在线事务处理 (OLTP)

💡 核心开发建议
在使用 InnoDB 时,写操作(UPDATE/DELETE)一定要尽量走唯一索引或普通索引,这样才能精准利用行级锁。如果 WHERE 条件没有命中索引,会导致全表扫描并锁定所有行记录,严重拖垮数据库并发性能。

00:00
00:00