在MySQL中,InnoDB引擎通过Next-Key Locking技术来解决幻读问题。幻读是一种事务并发问题,通常出现在Repeatable Read隔离级别下的范围查询操作中。幻读的现象是,事务在查询时多次执行相同的范围查询,但由于其他事务的插入或删除操作导致结果不一致,出现“幻觉”一样的记录。

Next-Key Locking 技术结合了 行锁(Record Lock)间隙锁(Gap Lock),通过锁定范围内的记录和它们之间的间隙,防止其他事务在这些锁定的区域内插入或删除数据,从而避免了幻读问题。

一、什么是Next-Key Locking?

Next-Key Locking 是一种 锁定区间 的机制,它由两部分组成:

  1. 行锁(Record Lock):锁定精确的一行数据,防止其他事务对该行数据的修改。
  2. 间隙锁(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的行,以及每一行数据之间的“间隙”。具体锁定机制如下:

  1. 行锁(Record Lock):锁定所有符合条件的行,阻止其他事务修改这些行。
  2. 间隙锁(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=25age=28 这两行(Record Lock)。
  • 锁住age > 18age < 35 之间的所有间隙(Gap Lock),即阻止在 age=19age=34 之间插入新行。

这保证了在当前事务提交之前,其他事务无法在查询的范围内插入、删除或修改数据,从而避免了幻读。

三、Next-Key Locking 的实现机制

  1. Record Lock(行锁):行锁是一种精确的锁,它只会锁定某个特定的行,防止其他事务修改该行数据。行锁可以确保事务中的读写操作对已经存在的数据行保持一致。
  2. Gap Lock(间隙锁):间隙锁是一种范围锁,它锁定数据行之间的间隙。它不会锁定实际的数据行,而是锁定行之间的空隙,防止其他事务在这些空隙中插入新的记录。这种锁用来解决幻读问题。
  3. Next-Key Locking(行锁 + 间隙锁):Next-Key Locking 结合了行锁和间隙锁,它不仅锁住了精确的数据行,还锁住了数据行之间的间隙。这样,Next-Key Locking 能有效防止其他事务在当前查询的范围内插入新数据,从而避免幻读。

四、Next-Key Locking 解决幻读的过程

Next-Key Locking 是在Repeatable Read隔离级别中使用的,流程大致如下:

  1. 事务A执行一个范围查询,例如SELECT * FROM users WHERE age BETWEEN 20 AND 30 FOR UPDATE;。此时,InnoDB 会使用 Next-Key Locking 锁住范围内的数据行和间隙,阻止其他事务在该范围内插入新的记录。
  2. 事务B尝试在age=26的位置插入一条新记录。由于事务A已经通过Next-Key Locking锁住了age=25age=30之间的间隙,事务B将被阻塞,直到事务A提交或回滚。
  3. 事务A提交或回滚后,事务B才能成功插入数据。如果事务A没有锁定这个范围,事务B插入数据后,事务A再进行范围查询时,结果就会不同,导致幻读的产生。

通过这种方式,Next-Key Locking 解决了由于并发插入导致的幻读问题。

五、Next-Key Locking 的优势与限制

优势

  • 解决幻读问题:Next-Key Locking 能有效防止在范围查询时产生幻读,保证事务的一致性。
  • 增强数据安全性:锁住查询范围内的间隙,防止其他事务在未提交的情况下对数据进行插入或修改,保证事务中的数据一致性。

限制

  • 降低并发性能:Next-Key Locking 的锁粒度较大,可能会锁定大量的行和间隙,导致系统的并发性能下降。
  • 间隙锁的开销:间隙锁会导致无法插入数据到锁定范围内的空隙中,这在某些场景下可能影响数据写入效率,尤其是在高并发写入的场景。

六、Next-Key Locking 的实际使用场景

  1. 银行系统中的余额查询

    • 在银行系统中,用户查询账户余额时可能会执行范围查询(例如,查询特定时间段的交易记录)。通过Next-Key Locking,系统可以防止其他事务在这个时间段内插入新的交易记录,确保用户每次查询得到的一致结果。
  2. 电商系统中的订单查询
    • 在电商平台中,用户查询某一时间段的订单时,可能需要保证查询过程中订单数据的一致性。通过Next-Key Locking,避免其他用户在订单查询期间插入新的订单,确保订单数据的一致性。

七、总结

Next-Key Locking 通过将行锁和间隙锁结合起来,解决了MySQL中Repeatable Read隔离级别下的幻读问题。它不仅锁住了查询范围内的具体数据行,还锁住了数据行之间的空隙,防止了新数据的插入。虽然这种锁机制能有效解决并发环境下的数据一致性问题,但也会带来并发性能的下降,需要在实际业务场景中权衡使用。

看了那么久别人写的内容,自己整理,总结归纳一下。言简意赅

MySQL 通过 Next-Key Locking 技术(行锁+间隙锁)避免幻读问题的更多相关文章

  1. (10)MySQL进阶篇SQL优化(InnoDB锁-间隙锁)

    1.概述 当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁:对于键值在条件范围内但并不存在的记录,叫做"间隙(GAP)&quo ...

  2. InnoDB的锁机制浅析(三)—幻读

    文章总共分为五个部分: InnoDB的锁机制浅析(一)-基本概念/兼容矩阵 InnoDB的锁机制浅析(二)-探索InnoDB中的锁(Record锁/Gap锁/Next-key锁/插入意向锁) Inno ...

  3. 【Mysql】表锁 行锁 记录锁 间隙锁

    Mysql中的锁 基于锁的属性分类:共享锁.排他锁. 基于锁的状态分类:意向共享锁.意向排它锁 根据锁的粒度分类:全局锁.页锁.表级锁.行锁(记录锁.间隙锁.和临键锁),实际上的锁就这些,上面两种分类 ...

  4. MySQL锁(三)行锁:幻读是什么?如何解决幻读?

    概述 前面两篇文章介绍了MySQL的全局锁和表级锁,今天就介绍一下MySQL的行锁. MySQL的行锁是各个引擎内部实现的,不是所有的引擎支持行锁,例如MyISAM就不支持行锁. 不支持行锁就意味着在 ...

  5. mysql锁机制之间隙锁(Next-Key锁)(五)

    间隙锁(Next-Key锁) 当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的 索引项加锁:对于键值在条件范围内但并不存在的记录,叫做“间隙(GA ...

  6. Mysql 锁和锁算法

    相关命令: show engines;  查看数据库支持的引擎 show variables like '%storage_engine%';   查看数据库默认的引擎 select @@global ...

  7. Mysql 间隙锁原理,以及Repeatable Read隔离级别下可以防止幻读原理(百度)

    Mysql知识实在太丰富了,前几天百度的面试官问我MySql在Repeatable Read下面是否会有幻读出现,我说按照事务的特性当然会有, 但是面试官却说 Mysql 在Repeatable Re ...

  8. mysql事务之一:MySQL数据库事务隔离级别(Transaction Isolation Level)及锁的实现原理

    一.数据库隔离级别 数据库隔离级别有四种,应用<高性能mysql>一书中的说明: 然后说说修改事务隔离级别的方法: 1.全局修改,修改mysql.ini配置文件,在最后加上 1 #可选参数 ...

  9. mysql 隔离级别与间隙锁等

    数据库隔离级 SQL标准中DB隔离级别有: read uncommitted:可以读到其它transaction 未提交数据 read committed:可以读到其它transaction 已提交数 ...

  10. mysql间隙锁

    什么是间隙锁(gap lock)? 间隙锁是一个在索引记录之间的间隙上的锁. 间隙锁的作用? 保证某个间隙内的数据在锁定情况下不会发生任何变化.比如我mysql默认隔离级别下的可重复读(RR). 当使 ...

随机推荐

  1. 从.net开发做到云原生运维(一)——从.net framework过渡到.net core

    1. 前言 序篇讲了自己的一些感悟和经历,从这章开始就开始讲一些.net技术栈的东西了. 2. .net framework和.net core对比 .NET Framework 概述 .NET Fr ...

  2. 【GPU】如何两周内零经验手搓一个GPU | 美国工程师极限挑战 | 重写三次 | CUDA | SIMD | ISA指令集 | Verilog | OpenLane

    地址: https://www.youtube.com/watch?v=FTh-c2ek6PU

  3. C# 遇见System.Net.Http不兼容的解决方案

    背景 假设我有一个项目A,调用B项目里面的HttpClient.A里面的System.Net.Http引用路径为(版本4.0.0.0) C:\Program Files (x86)\Reference ...

  4. Unity编辑器批量设置图片格式

    在游戏开发中,经常需要批量设置图片的格式为Sprite类型,手动设置太麻烦,下面的编辑器脚本实现选中文件夹右键/Texture/SetAllImagesToSpriteType实现批量设置图片格式,具 ...

  5. 利用Stream实现简单的等差数列求和

    我们都熟知高斯的故事,认识等差数列也是从这个故事开始的,编程课程为了练习for循环,也在不断的练习这个从1加到100的例子,那么原始的办法是这样的: int sum1 = 0; for (int i ...

  6. Linux中级——“驱动” 控制硬件必须学会的底层知识

    驱动认知 1. 什么是驱动 驱动就是对底层硬件设备的操作进行封装,并向上层提供函数接口. 设备分类: linux系统将设备分为3类:字符设备.块设备.网络设备. 字符设备:指只能一个字节一个字节读写的 ...

  7. Atcoder ABC364 D-F

    Atcoder ABC364 D-F D - K-th Nearest 链接: D - K-th Nearest (atcoder.jp) 简要题意: 问题陈述 在一条数线上有 \(N+Q\) 个点 ...

  8. 官网使用conda&pip安装PyTorch命令总结(包含各版本)

    原网页https://pytorch.org/get-started/previous-versions/ 因为有时访问该网站比较慢,所以本博客记录该网页内容 Installing previous ...

  9. hass安装tileboard详细

    首先下载tileboard https://github.com/resoai/TileBoard/releases/download/v2.10.2/TileBoard.zip 下载之后前往hass ...

  10. 全网最适合入门的面向对象编程教程:41 Python 常用复合数据类型-队列(FIFO、LIFO、优先级队列、双端队列和环形队列)

    全网最适合入门的面向对象编程教程:41 Python 常用复合数据类型-队列(FIFO.LIFO.优先级队列.双端队列和环形队列) 摘要: 在 Python 中,队列(Queue)是一种常用的数据结构 ...