InnoDB 有哪几类行锁?

2024-10-03 23:38:03 浏览数 (2)

行级锁每次操作均会锁定对应的行数据,锁定粒度最小,致使锁冲突发生的可能性最低,因而并发度最高。它被应用于 InnoDB 存储引擎之中,要知道,InnoDB 的数据是依据索引来组织的,行锁通过对索引上的索引项加锁来实现,并非针对记录加锁。

同时,InnoDB 行锁包含共享锁(S)和排他锁(X) ,而行锁的共享锁和排他锁还能够继续细分成为三类:记录锁间隙锁临键锁

记录锁(Record Lock)

  • 作用:锁定表中的单行记录,防止其他事务对其进行update或delete。
  • 情况:当执行精确匹配查询(例如 WHERE id = 1 )并且查询的索引是唯一索引时,会对匹配的行加记录锁。
  • 示例:假设有表 students ,其中 id 是主键,事务 A 执行 SELECT * FROM students WHERE id = 15 FOR UPDATE; ,此时就会对 id = 15 的这行数据加记录锁。
  • 图示:

间隙锁(Gap Lock)

  • 作用:锁定一个范围,但不包含记录本身,防止其他事务在这个间隙上insert,主要用于防止幻读。
  • 情况:在可重复读隔离级别下,对于范围查询(如 WHERE id > 5 ),如果查询的索引不是唯一索引,会使用间隙锁。
  • 示例:事务 B 执行 SELECT * FROM students WHERE age > 20 FOR UPDATE; ,假设 age 列上没有唯一索引,此时会对 age 值大于 20 的间隙加间隙锁。
  • 图示:

临键锁(Next-Key Lock)

  • 作用:是记录锁和间隙锁的组合,既锁住记录,又锁住记录前面的间隙。
  • 情况:在可重复读隔离级别下,当使用范围查询且查询的索引是唯一索引时,会使用临键锁。
  • 示例:事务 C 执行 SELECT * FROM students WHERE id >= 20 FOR UPDATE; ,如果 id 是唯一索引,会对 id >= 20的范围加临键锁。
  • 图示:

行锁

InnoDB的行锁包含共享锁(S)和排他锁(X),在实现方式上表现为记录锁、间隙锁、临键锁。

共享锁(S 锁):允许其他事务同时读取被锁定的数据,但不允许修改。

排他锁(X 锁):则具有排他性,不允许其他事务获取共享锁或排他锁来访问被锁定的数据。

两种锁的兼容情况如下:

锁类型

共享锁(S 锁)

排他锁(X 锁)

共享锁(S 锁)

兼容(✔)

冲突(×)

共享锁(S 锁) | 兼容(✔) | 冲突(×)

常见的SQL,加锁情况:

| SQL | 行锁类型 | 加锁情况 |

| --- | --- | --- |

| SELECT | 无锁 | 没有任何加锁 |

| SELECT ... LOCK IN SHARE MODE | 共享锁(S 锁) | 需要在SELECT 查询末尾加上‘LOCK IN SHARE MODE’ |

| SELECT ... FOR UPDATE | 排他锁(X 锁) | 需要在SELECT 查询末尾加上‘FOR UPDATE’ |

| INSERT | 排他锁(X 锁) | 自动会加上排他锁 |

| UPDATE | 排他锁(X 锁) | 自动会加上排他锁 |

| DELETE | 排他锁(X 锁) | 自动会加上排他锁 |

总结

总之,InnoDB 丰富多样的行锁机制,从共享锁与排他锁的大分类,到记录锁、间隙锁和临键锁的具体形式,为数据库的事务处理和并发操作提供了精细且可靠的控制手段。熟悉并驾驭这些行锁,是实现高性能、稳定可靠的数据库系统的重要基石。

0 人点赞