~码铃薯~

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

介绍一下MySQL中的表锁、行锁、间隙锁,以及他们都在什么情况下会使用

表锁 (Table Lock)

1. 是什么:
表锁是锁住整张表,开销小,加锁快,但锁粒度大,发生锁冲突的概率最高,并发度最低。

2. 使用场景:

  • MyISAM引擎:由于不支持事务和行锁,默认全用表锁。
  • InnoDB中的DDL操作:执行 ALTER TABLE 等修改表结构的语句时,会加表锁。
  • 全表扫描的更新:如果一条 UPDATEDELETE 语句没有命中索引,InnoDB会锁住整张表(行锁升级为表锁,这是面试大坑!)。
  • 备份场景:比如前面提到的 FLUSH TABLES WITH READ LOCK (FTWRL)(注意:这是一条sql命令关闭所有打开的表,同时对于所有数据库中的表都加一个读锁,直到显式地执行unlock tables,该操作常
    常用于数据备份的时候。),就是加全局读锁。

行锁 (Row Lock)

1. 是什么:
锁住单行记录。开销大,加锁慢,会出现死锁,但锁粒度最小,并发度最高。InnoDB默认支持行锁。
2. 分类(基于模式):

  • 共享锁(S锁 / 读锁)SELECT ... LOCK IN SHARE MODE; 允许其他事务读,阻止写。
  • 排他锁(X锁 / 写锁)SELECT ... FOR UPDATE;UPDATE / DELETE 语句。允许事务读写,阻止其他事务读写。

3. 记录锁(Record Lock):
行锁的典型实现就是记录锁,锁定的是索引记录本身(注意:是索引记录,不是数据行!)。
4. 使用场景:

  • 高并发下的精确更新:如 UPDATE user SET age = 18 WHERE id = 10id 是主键或唯一索引)。
  • 悲观锁的实现:通过在SQL中显式加 FOR UPDATE 来保证并发安全。

5. 面试加分点:
“行锁的加锁是基于索引的,如果一条SQL走的是辅助索引,那么不仅会锁住辅助索引记录,还会回表锁住对应的主键索引记录。”

四、 间隙锁 (Gap Lock)

1. 是什么:
间隙锁锁定的是索引记录之间的“间隙”(开区间),或者第一条记录之前的间隙,或者最后一条记录之后的间隙。它不锁定记录本身。
2. 核心作用:
防止幻读。在“可重复读(RR)”隔离级别下,如果一个事务在范围内查询,另一个事务在这个范围内插入了新数据,为了避免前一个事务两次查询结果不一致(幻读),InnoDB引入了间隙锁,阻止其他事务在这个间隙内插入数据。
3. 特点:

  • 只在 RR 隔离级别下生效(RC隔离级别下没有间隙锁)。
  • 间隙锁之间不互斥:两个事务可以同时持有同一个间隙的锁。
  • 与插入操作(Insert)互斥。

4. 组合武器:临键锁 (Next-Key Lock)
在RR级别下,InnoDB默认使用的是临键锁,它是记录锁 + 间隙锁的组合。锁定的是一个左开右闭的区间,例如 (5, 10]

  • 如果是唯一索引的等值查询,且记录存在,Next-Key Lock 会退化为记录锁。
  • 如果是等值查询,但记录不存在,会退化为间隙锁。

5. 使用场景:

  • RR隔离级别下的范围查询:如 SELECT * FROM user WHERE age > 10 FOR UPDATE; 这会将 (10, +∞) 的间隙全部锁住,其他事务无法插入 age > 10 的数据。
  • 等值查询不存在的记录:如 SELECT * FROM user WHERE id = 15 FOR UPDATE; 如果 id=15 不存在,会锁住 (10, 20) 这个间隙。
posted on 2026-09-20 16:05  ~码铃薯~  阅读(6)  评论(0)    收藏  举报