数据库锁之行级锁、记录锁、间隙锁和临键锁

1. 行级锁

InnoDB 引擎支持行级锁,而MyISAM 引擎不支持行级锁,只支持表级锁。行级锁是基于索引实现的

对于普通的select语句,是不会加记录锁的,因为它属于快照读,通过在MVCC中的undo log版本链实现。如果要在查询时对记录加行锁,可以使用下面这两个方式,这种查询会加锁的语句称为锁定读。

复制代码
//对读取的记录加共享锁
select ... lock in share mode;

//对读取的记录加独占锁
select ... for update;

对于DML语句(update、delete和insert)来说,其在执行过程中会默认加上for update, 系统会为目标行加上行级锁。

需要注意的是, 行级锁依赖索引**, 如果查询的条件字段** xx****上没有索引,那么 InnoDB 无法精确定位查询结果中涉及的行,只能通过全表扫描来查找满足条件的记录。当进行全表扫描时,InnoDB 会对表中的每行数据都加上行级锁,相当于把整个表都锁住了,以确保在扫描期间没有其他事务对表进行修改。因此,这种情况下,数据库将 退化为表级锁**,锁住整个表,阻止其他事务对表进行任何修改操作,直到当前事务完成。**

因此对于update、delete、select ... for update 等具有加锁性质的语句,一定要检查语句是否走了索引,如果是全表扫描的话,会把整个表都锁住。

2. 记录锁(Record Lock)

记录锁 是一种特殊的行级锁,它锁定的是数据库中的一条具体记录 。在 InnoDB 存储引擎中,记录锁会锁定索引中的一条记录

记录锁是有 S 锁和 X 锁之分的:

  • 当一个事务对一条记录加了 S 型记录锁后,其他事务也可以继续对该记录加 S 型记录锁(S 型与 S 锁兼容),但是不可以对该记录加 X 型记录锁(S 型与 X 锁不兼容);

  • 当一个事务对一条记录加了 X 型记录锁后,其他事务既不可以对该记录加 S 型记录锁(S 型与 X 锁不兼容),也不可以对该记录加 X 型记录锁(X 型与 X 锁不兼容)。

    select * from t_test where id = 1 for update

对 t_test 表中主键 id 为 1 的这条记录加上 X 型的记录锁,这样其他事务就无法对这条记录进行修改了。

3. 间隙锁(Gap Lock)

间隙锁是一种特殊的锁机制,作用于索引之间的"间隙",只存在于可重复读隔离级别,用于防止在锁定的记录前后插入新记录。它主要用于防止 幻读(Phantom Read),确保在并发事务中,查询结果在事务期间不会因其他事务插入新的行而发生变化。

假设,表中有一个范围 id 为(3,5)间隙锁,那么其他事务就无法插入 id = 4 这条记录了,这样就有效的防止幻读现象的发生。

间隙锁虽然存在 X 型间隙锁和 S 型间隙锁,但是并没有什么区别,间隙锁之间是兼容的,即两个事务可以同时持有包含共同间隙范围的间隙锁,并不存在互斥关系,因为间隙锁的目的是防止插入幻影记录而提出的

4. 临键锁(Next-Key Lock)

临键锁(Next-Key Lock)是记录锁和间隙锁的结合,锁定一个范围,并且锁定记录本身。

假设,表中有一个范围 id 为(3,5] 的 next-key lock,那么其他事务即不能插入 id = 4 记录,也不能修改 id = 5 这条记录。

所以,next-key lock 即能保护该记录,又能阻止其他事务将新纪录插入到被保护记录前面的间隙中。

5. 总结:

  • 行级锁 是最常见的锁机制,用于锁定单个行记录,确保并发事务之间的数据一致性,适合高并发场景。
  • 记录锁 是一种作用于索引记录的行级锁,通常在涉及具体行的查询或修改时使用,确保其他事务无法修改特定记录。
  • 间隙锁 则用于锁定索引记录之间的间隙,防止其他事务插入新的行,解决并发事务中可能出现的幻读问题。
相关推荐
技术宝哥1 小时前
Redis(2):Redis + Lua为什么可以实现原子性
数据库·redis·lua
学地理的小胖砸2 小时前
【Python 操作 MySQL 数据库】
数据库·python·mysql
dddaidai1233 小时前
Redis解析
数据库·redis·缓存
数据库幼崽3 小时前
MySQL 8.0 OCP 1Z0-908 121-130题
数据库·mysql·ocp
Amctwd3 小时前
【SQL】如何在 SQL 中统计结构化字符串的特征频率
数据库·sql
betazhou4 小时前
基于Linux环境实现Oracle goldengate远程抽取MySQL同步数据到MySQL
linux·数据库·mysql·oracle·ogg
lyrhhhhhhhh4 小时前
Spring 框架 JDBC 模板技术详解
java·数据库·spring
喝醉的小喵5 小时前
【mysql】并发 Insert 的死锁问题 第二弹
数据库·后端·mysql·死锁
付出不多6 小时前
Linux——mysql主从复制与读写分离
数据库·mysql
初次见面我叫泰隆6 小时前
MySQL——1、数据库基础
数据库·adb