MySQL 通过 Next-Key Locking 技术(行锁+间隙锁)避免幻读问题
在MySQL中,InnoDB引擎通过Next-Key Locking技术来解决幻读问题。幻读是一种事务并发问题,通常出现在Repeatable Read
隔离级别下的范围查询操作中。幻读的现象是,事务在查询时多次执行相同的范围查询,但由于其他事务的插入或删除操作导致结果不一致,出现“幻觉”一样的记录。
Next-Key Locking 技术结合了 行锁(Record Lock) 和 间隙锁(Gap Lock),通过锁定范围内的记录和它们之间的间隙,防止其他事务在这些锁定的区域内插入或删除数据,从而避免了幻读问题。
一、什么是Next-Key Locking?
Next-Key Locking 是一种 锁定区间 的机制,它由两部分组成:
- 行锁(Record Lock):锁定精确的一行数据,防止其他事务对该行数据的修改。
- 间隙锁(Gap Lock):锁定一行数据之间的“间隙”,防止其他事务在该间隙中插入新数据。
Next-Key Locking 锁住了当前查询的行及其“前后”的间隙,这样不仅可以防止已有记录的修改,还能防止在查询范围内插入新数据,避免了幻读问题。
二、Next-Key Locking 的原理
在Repeatable Read
隔离级别下,当执行范围查询时,InnoDB会通过Next-Key Locking在范围内锁定所有满足条件的行及其相邻的间隙。例如,执行下面的SQL语句:
SELECT * FROM users WHERE age BETWEEN 20 AND 30 FOR UPDATE;
这个查询会锁定users
表中所有满足age BETWEEN 20 AND 30
的行,以及每一行数据之间的“间隙”。具体锁定机制如下:
- 行锁(Record Lock):锁定所有符合条件的行,阻止其他事务修改这些行。
- 间隙锁(Gap Lock):锁定查询范围内的行之间的“间隙”,阻止其他事务在这些间隙中插入新行。
假设当前数据如下:
id | age
---------
1 | 18
2 | 25
3 | 28
4 | 35
执行 SELECT * FROM users WHERE age BETWEEN 20 AND 30 FOR UPDATE;
时,Next-Key Locking 会做如下操作:
- 锁住
age=25
和age=28
这两行(Record Lock)。 - 锁住
age > 18
到age < 35
之间的所有间隙(Gap Lock),即阻止在age=19
到age=34
之间插入新行。
这保证了在当前事务提交之前,其他事务无法在查询的范围内插入、删除或修改数据,从而避免了幻读。
三、Next-Key Locking 的实现机制
- Record Lock(行锁):行锁是一种精确的锁,它只会锁定某个特定的行,防止其他事务修改该行数据。行锁可以确保事务中的读写操作对已经存在的数据行保持一致。
- Gap Lock(间隙锁):间隙锁是一种范围锁,它锁定数据行之间的间隙。它不会锁定实际的数据行,而是锁定行之间的空隙,防止其他事务在这些空隙中插入新的记录。这种锁用来解决幻读问题。
- Next-Key Locking(行锁 + 间隙锁):Next-Key Locking 结合了行锁和间隙锁,它不仅锁住了精确的数据行,还锁住了数据行之间的间隙。这样,Next-Key Locking 能有效防止其他事务在当前查询的范围内插入新数据,从而避免幻读。
四、Next-Key Locking 解决幻读的过程
Next-Key Locking 是在Repeatable Read
隔离级别中使用的,流程大致如下:
- 事务A执行一个范围查询,例如
SELECT * FROM users WHERE age BETWEEN 20 AND 30 FOR UPDATE;
。此时,InnoDB 会使用 Next-Key Locking 锁住范围内的数据行和间隙,阻止其他事务在该范围内插入新的记录。 - 事务B尝试在
age=26
的位置插入一条新记录。由于事务A已经通过Next-Key Locking锁住了age=25
到age=30
之间的间隙,事务B将被阻塞,直到事务A提交或回滚。 - 事务A提交或回滚后,事务B才能成功插入数据。如果事务A没有锁定这个范围,事务B插入数据后,事务A再进行范围查询时,结果就会不同,导致幻读的产生。
通过这种方式,Next-Key Locking 解决了由于并发插入导致的幻读问题。
五、Next-Key Locking 的优势与限制
优势:
- 解决幻读问题:Next-Key Locking 能有效防止在范围查询时产生幻读,保证事务的一致性。
- 增强数据安全性:锁住查询范围内的间隙,防止其他事务在未提交的情况下对数据进行插入或修改,保证事务中的数据一致性。
限制:
- 降低并发性能:Next-Key Locking 的锁粒度较大,可能会锁定大量的行和间隙,导致系统的并发性能下降。
- 间隙锁的开销:间隙锁会导致无法插入数据到锁定范围内的空隙中,这在某些场景下可能影响数据写入效率,尤其是在高并发写入的场景。
六、Next-Key Locking 的实际使用场景
- 银行系统中的余额查询:
- 在银行系统中,用户查询账户余额时可能会执行范围查询(例如,查询特定时间段的交易记录)。通过Next-Key Locking,系统可以防止其他事务在这个时间段内插入新的交易记录,确保用户每次查询得到的一致结果。
- 电商系统中的订单查询:
- 在电商平台中,用户查询某一时间段的订单时,可能需要保证查询过程中订单数据的一致性。通过Next-Key Locking,避免其他用户在订单查询期间插入新的订单,确保订单数据的一致性。
七、总结
Next-Key Locking 通过将行锁和间隙锁结合起来,解决了MySQL中Repeatable Read
隔离级别下的幻读问题。它不仅锁住了查询范围内的具体数据行,还锁住了数据行之间的空隙,防止了新数据的插入。虽然这种锁机制能有效解决并发环境下的数据一致性问题,但也会带来并发性能的下降,需要在实际业务场景中权衡使用。
看了那么久别人写的内容,自己整理,总结归纳一下。言简意赅
MySQL 通过 Next-Key Locking 技术(行锁+间隙锁)避免幻读问题的更多相关文章
- (10)MySQL进阶篇SQL优化(InnoDB锁-间隙锁)
1.概述 当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁:对于键值在条件范围内但并不存在的记录,叫做"间隙(GAP)&quo ...
- InnoDB的锁机制浅析(三)—幻读
文章总共分为五个部分: InnoDB的锁机制浅析(一)-基本概念/兼容矩阵 InnoDB的锁机制浅析(二)-探索InnoDB中的锁(Record锁/Gap锁/Next-key锁/插入意向锁) Inno ...
- 【Mysql】表锁 行锁 记录锁 间隙锁
Mysql中的锁 基于锁的属性分类:共享锁.排他锁. 基于锁的状态分类:意向共享锁.意向排它锁 根据锁的粒度分类:全局锁.页锁.表级锁.行锁(记录锁.间隙锁.和临键锁),实际上的锁就这些,上面两种分类 ...
- MySQL锁(三)行锁:幻读是什么?如何解决幻读?
概述 前面两篇文章介绍了MySQL的全局锁和表级锁,今天就介绍一下MySQL的行锁. MySQL的行锁是各个引擎内部实现的,不是所有的引擎支持行锁,例如MyISAM就不支持行锁. 不支持行锁就意味着在 ...
- mysql锁机制之间隙锁(Next-Key锁)(五)
间隙锁(Next-Key锁) 当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的 索引项加锁:对于键值在条件范围内但并不存在的记录,叫做“间隙(GA ...
- Mysql 锁和锁算法
相关命令: show engines; 查看数据库支持的引擎 show variables like '%storage_engine%'; 查看数据库默认的引擎 select @@global ...
- Mysql 间隙锁原理,以及Repeatable Read隔离级别下可以防止幻读原理(百度)
Mysql知识实在太丰富了,前几天百度的面试官问我MySql在Repeatable Read下面是否会有幻读出现,我说按照事务的特性当然会有, 但是面试官却说 Mysql 在Repeatable Re ...
- mysql事务之一:MySQL数据库事务隔离级别(Transaction Isolation Level)及锁的实现原理
一.数据库隔离级别 数据库隔离级别有四种,应用<高性能mysql>一书中的说明: 然后说说修改事务隔离级别的方法: 1.全局修改,修改mysql.ini配置文件,在最后加上 1 #可选参数 ...
- mysql 隔离级别与间隙锁等
数据库隔离级 SQL标准中DB隔离级别有: read uncommitted:可以读到其它transaction 未提交数据 read committed:可以读到其它transaction 已提交数 ...
- mysql间隙锁
什么是间隙锁(gap lock)? 间隙锁是一个在索引记录之间的间隙上的锁. 间隙锁的作用? 保证某个间隙内的数据在锁定情况下不会发生任何变化.比如我mysql默认隔离级别下的可重复读(RR). 当使 ...
随机推荐
- “refer to”和“refer to as”在英语中的用法有所不同
"refer to"和"refer to as"在英语中的用法有所不同,具体区别如下: Refer to "Refer to"意为" ...
- signal-slot:python版本的多进程通信的信号与槽机制(编程模式)的库(library) —— 强化学习ppo算法库sample-factory的多进程包装器,实现类似Qt的多进程编程模式(信号与槽机制) —— python3.12版本下成功通过测试
什么是 Qt signal-slot库项目地址: https://github.com/alex-petrenko/signal-slot 该库实现的主要原理: 要注意这个项目的library只是对原 ...
- 鹏程实验室,启智平台,openI平台,积分兑换新标准
2024-02-13 11:12:21 星期二 地址: https://openi.pcl.ac.cn/reward/point/rule
- ( Ubuntu环境下 )Vim插件推荐-Python自动补齐Vim插件jedi-vim的安装(使用插件管理器vundle进行安装)
Ubuntu系统下,为 Vim 安装python自动补齐的插件 jedi-vim . 1. jedi-vim安装依赖 首先,jedi-vim插件需要当前Vim版本支持python,在终端输 ...
- 使用Redis时的vm.overcommit_memory内存分配控制
最近在使用Redis的时候遇到了linux系统中的vm.overcommit_memory参数设置,对此不是很了解,于是研究了一下,有了本文. ============================ ...
- Pytorch学习率更新
如需了解示例完整代码及其后续内容请访问: https://www.emperinter.info/2020/08/01/learning-rate-in-pytorch/ 缘由 自己在尝试了官方的代码 ...
- ComfyUI插件:efficiency-nodes-comfyui节点
前言: 学习ComfyUI是一场持久战, efficiency-nodes-comfyui是提高工作流创造效率的工具,包含效率节点整合工作流中的基础功能,比如Efficient Loader节点相当于 ...
- 【Playwright+Python】系列教程(八)鉴权Authentication的使用
写在前面 还是有些絮叨的感觉,官方翻译和某些博主写那个玩楞,基本都是软件直接翻译后的产物. 读起来生硬不说,甚至有的时候不到是什么意思,真的是实在不敢恭维. 到底是什么意思? 就是你已经登陆过一次,在 ...
- Docker 之 RabbitMQ安装教程 基于腾讯云
由于需要学习RabbitMQ(主要是项目启动了mq本地却没有服务控制台老是在连mq,致使我热部署都不知道到底成功没),所以才有了这个教程,下面介绍RabbitMQ准备工作 下载所需环境 yum -y ...
- Java核心技术之Date相关
import java.time.DayOfWeek; import java.time.LocalDate; import java.util.Scanner; /** * @author Suns ...