【Mysql】next-key 锁范围

背景

Mysql RR场景下通过next-key 锁解决了幻读的问题,而幻读通常是由 insert 新增的数据导致。所以next-key锁最终通过锁机制防止了一定条件下的新增数据从而解决了幻读问题。

规律

next-key锁可以由以下几条规律总结出锁范围

  • next-key会对查询过程中访问到的对象进行加锁
  • next-key锁通常是左开右闭的
  • 在唯一索引上做等值查询时,next-key锁会退化成行锁
  • 在做等值查询时,查询最后访问到的一个对象所加的next-key上不包含右节点,也就是变成了两边都是开区间
  • 在唯一索引上做范围查询时,会访问到下一个不满足条件的对象上(Mysql 5.7版本)

实例

表数据结构
id 列是主键,c列上有普通索引,表内数据如下

idcd
000
555
101010
151515
202020
252525

等值查询间隙锁

在这里插入图片描述
第一个 update 语句会先找 id = 7 的数据,所以在 主键索引上的 B+树上做查询时,会先扫描 id = 7 的这一行,但是表内没有这一条数据,所以找到了比他大的第一条数据,也就是 id = 10 这一行。
再根据next-key加锁规律进行加锁,先加一个左开右闭的锁,再因为做等值查询时,最后不满足条件的第一条数据变成左开右开区间,从而给 (5, 10) 这一个范围加上了锁。
最终导致 insert 8 插入失败,update 10 更新成功。

非唯一索引等值锁

在这里插入图片描述
第一个 select … … lock in share mode 会先在索引树上找到 c = 5, id = 5 这一行,因为不知道有其他的 c = 5,会继续向下找,找到 c = 10, id = 10 这一行并终止查询。
所以根据规律,会现在索引 c 上加 (0, 5] 和 (5, 10] 上加锁,并因为做等值查询,将范围改为 (0, 5] 和 (5, 10)。
在做 update id = 5 这一行数据时,因为 修改对象是 id = 5 不在 索引 c 上,所以修改成功。
而做 insert c = 7 时,因为在锁区间内,所以 插入失败。
在这里不对 主键 索引 id 上加锁,是因为 select id … lock in share mode 的特殊性,首先因为覆盖索引的特殊性, id 列本身就在 索引 c 的B+树叶子节点上,所以不涉及到回表,访问到的对象也只有 索引 c 上的树节点。

如果将 lock in share mode 换成 for update。此时,update 就会被 block 住,因为 Mysql 会认为这将会造成一条更新,所以会将锁向 主键索引传递,为对应的主键索引数据行加锁。

主键索引范围锁

在这里插入图片描述

第一个 select 语言会扫描所有 id >= 10 并且 id < 11 的 主键索引数据行,所以会先找到 id = 10 这一行,并且接着向下扫描扫描到 id = 15 这一行时,不满足条件,结束查询。
所以根据规律会先对(5, 10] 和 (10,15] 上加锁,因为唯一索引加等值查询的原因,第一个next-key锁退化为行锁,最终变成[10,15] 这个范围。
从而导致 insert 8 成功,insert 13 失败,update 15 失败。

非唯一索引范围锁

在这里插入图片描述
第一个 select 语言会扫描所有 c >= 10 并且 c < 11 的 主键索引数据行,所以会先找到 c = 10 这一行,并且接着向下扫描扫描到 c = 15 这一行时,不满足条件,结束查询。
所以根据规律会先对(5, 10] 和 (10,15] 上加锁。

这里和上面不同,首先是因为 做 c>= 10 时,索引 c 不是唯一索引,所以不会退化为行锁
其次在做 c < 11 时,不是 等值查询,所以也不用做 左开右开的退化。

唯一索引范围锁 bug

在这里插入图片描述
这个查询会扫描所有 id > 10 并且 id <= 15 的 主键索引数据行,所以会先找到比10大的第一行 也就是 id = 15 这一行,并且接着向下扫描扫描到 id = 15 这一行时,正常会因为 唯一索引的原因,不会存在 第二个 id = 15 了,但是因为规律第五条的原因会继续向下扫描到 id = 20 这一行,结束查询。
所以最终加锁范围是 (10,15] 和 (15, 20] 这两个区间。
导致 update 20 修改失败, insert 16 插入失败。

非唯一索引上存在"等值"的例子

此时,数据表中多一条 (30, 10, 30)的数据,此时数据表中数据为

idcd
000
555
101010
151515
202020
252525
301030

在这里插入图片描述

因为第一条 delete c = 10 ,会先扫描 索引 c 的 B+树上 c = 10 的数据行,接着因为 c 不是唯一索引,不知道 有没有其他的 c = 10 会继续向下扫描,知道扫描到 c = 15 时,不满足条件,结束查询。
此时,根据next - key 规律,会先加 (5, 10] 和 (10, 15] 锁,并因为等值查询的原因,第二段锁退化成左开右开,变成 (5, 10] 和 (10, 15) 锁区间。
最终导致 insert 12 插入失败,update 15 更新成功。

limit 语句加锁

此时,数据表中多一条 (30, 10, 30)的数据,此时数据表中数据为

idcd
000
555
101010
151515
202020
252525
301030

在这里插入图片描述
因为第一条 delete c = 10 ,会先扫描 索引 c 的 B+树上 c = 10 的数据行,也就是 c = 10, id = 10 和 c = 10, id = 30 这两条,此时因为 limit 2 的原因,扫描到这两条之后满足条件就退出查询了,不会继续向下扫描 c = 15 这一行。

所以加锁范围就仅仅是 (5, 10] 这一个区间了。
最终导致 insert 12 插入成功。

一个死锁的例子

在这里插入图片描述
next-key 锁由间隙锁(左开右开) 和 行锁组成,所以在某些情况下会出现 间隙锁加锁成功,行锁加锁失败的场景。
在这段语句中,Session A 做 select lock in share mode时,会对(5,10] 加锁,并且因为 share mode的原因是共享锁。

在做update c = 10 最终结果失败的,但是由于间隙锁和行锁的原因,Session B 的间隙锁加锁成功,c = 10 的行锁加锁失败。

Session A 此时又要插入 8,这个 8 在 Session B 的间隙锁区间内,所以也加锁失败,开始等待。

这个时候Session A 在等待 Session B 释放锁,Session B 又在等待 Session A 释放锁,构成死锁条件。

参考

Mysql 实战45讲 20节
Mysql 实战45讲 21节

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/130337.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

jenkins邮件告警

构建失败邮件通知 配置自己的邮箱 配置邮件服务&#xff0c;密码是授权码 添加构建后操作 扩展 配置流水线 添加扩展 钉钉通知 Jenkins安装钉钉插件 钉钉添加机器人 加签 https://oapi.dingtalk.com/robot/send?access_token98437f84ffb6cd64fa2d7698ef44191d49a11…

CSS特效005:绘制一个环环相扣的五个环

css实战中&#xff0c;怎么制作这样的一个环环相扣的五个环呢&#xff1f; 绘制五个圈圈很容易&#xff0c;关键是要环环相扣&#xff0c;尤其要注意环环相交部分的处理。这里要用到transform-style: preserve-3d; 和 transform: rotateY( 1deg ) 等关键的css技术。 效果图 源…

系列二十二、idea Live Templates

一、idea Live Templates 1.1、Java Group 1.1.1、fast fast 快速在类上添加注解Data AllArgsConstructor NoArgsConstructor Accessors(chain true) ToString(callSuper true) 1.1.2、getThreadName getThreadName快速获取当前线程的名字Thread.currentThread().getName…

Flink SQL自定义表值函数(Table Function)

使用场景&#xff1a; 表值函数即 UDTF&#xff0c;⽤于进⼀条数据&#xff0c;出多条数据的场景。 开发流程&#xff1a; 实现 org.apache.flink.table.functions.TableFunction 接⼝实现⼀个或者多个⾃定义的 eval 函数&#xff0c;名称必须叫做 eval&#xff0c;eval ⽅法…

Unity 场景优化策略

Unity 场景优化策略 GPU instancing 使用GPU Instancing可以将多个网格相同、材质相同、材质属性可以不同的物体合并为一个批次&#xff0c;从而减少Draw Calls的次数。这可以提高性能和渲染效率。 GPU instancing可用于绘制在场景中多次出现的几何体&#xff0c;例如树木或…

MIT6.5830 Lab1-GoDB实验记录(六)

MIT6.5830 Lab1-GoDB实验记录&#xff08;六&#xff09; – WhiteNights Site 标签&#xff1a;Golang 赛博坐牢之旅第一章第六节&#xff1a;接着上一节&#xff0c;补全heap_page剩下的函数。 开始坐牢 删除tuple 这个看起来…难度还没那么高&#xff0c;写一下试试吧。那…

HTTP和HTTPS详解

一)什么是HTTP协议 1)HTTP协议是倾向于相遇业务层次上面的一种协议&#xff0c;传输层协议主要考虑的是端对端之间的一个传输过程&#xff0c;TCP重点进行关注的是可靠传输&#xff1b;咱们的HTTP/1&#xff0c;HTTP/2是基于TCP的&#xff0c;但是咱们的HTTP/3是基于UDP的&…

QWidget背景图片在Qt Designer 中能显示但运行时不显示的解决方法

目录 1. 现象 2. 解决方法 3. 附录 1. 现象 今天想在QWidget中贴一张png图片作为背景图&#xff0c;在Qt Designer 能显示&#xff0c;但运行时&#xff0c;死活不显示背景图片。样式表设置如下&#xff1a; QWidget {border-image:url(:/untitled2/image/operpanel.png); }…

Linux 多线程控制详解

目录 多线程编临界资源访问 互斥锁 API 简述 初始化互斥量 互斥量加锁/解锁 互斥量加锁(非阻塞方式) 互斥量销毁 程序示例 多线程编执行顺序控制 信号量 API 简述 初始化信号量 信号量 P/V 操作 信号量申请(非阻塞方式) 信号量销毁 程序示例 条件变量 创建和销毁…

Mybatis-plus 内部提供的 ServiceImpl<M extends BaseMapper<T>, T> 学习总结

作用 当集成Mybatis-Plus 后&#xff0c;我们的大部分数据库操作都可以通过 XxxxxMapper &#xff0c;同时 Mybatis-plus 在Mapper 提供基本操作方法的同时&#xff0c;也提供类基础的 serviceImpl 来帮助我们完成一些常见的基本操作。 使用 一般情况下&#xff0c;我们首先…

Ipa Guard使用手册

使用手册 开始使用ipa guard代码混淆界面介绍文件混淆-界面介绍安装和登录Ipa Guard 相关教程 下载安装Ipa Guardipaguard注册和登录 下载安装Ipa Guard 可以前往ipaguard工具官网下载&#xff0c;工具是免费下载&#xff0c;免费体验使用的。下载地址是https://www.ipagua…

MS2358:96KHz、24bit 音频 ADC

MS2358 是带有采样速率 8kHz-96kHz 的立体声音频模数 转换器&#xff0c;适合于面向消费者的专业音频系统。 MS2358 通过使用增强型双位 Δ - ∑ 技术来实现其高精度 的特点。 MS2358 支持单端的模拟输入&#xff0c;所以不需要外部器 件&#xff0c;非常适合用于像 …

ChatGPT 宕机?OpenAI 将中断归咎于 DDoS 攻击

您的 ChatGPT 已关闭吗&#xff1f;您是否遇到 ChatGPT 问题&#xff0c;例如连接问题或遇到“长响应时出现网络错误”&#xff1f;– ChatGPT 遭受了一系列 DDoS 攻击&#xff0c;显然是由匿名苏丹组织策划的。 OpenAI 的 ChatGPT 是一款流行的人工智能聊天机器人&#xff0c;…

标本传送设备物联网应用案例|蓝蜂物联网一体化方案

标本传送设备物联网应用案例 标本传输系统被大量应用到现代医院场景中&#xff0c;系统各个设备的运行情况直接影响到整个医院系统的正常稳定&#xff0c;所以对于标本传输系统的实时监控和及时运维是维持医院稳定和规避风险的重中之重。 针对标本传输系统应用过程中的数据统…

ios安全加固 ios 加固方案

​ 目录 一、iOS加固保护原理 1.字符串混淆 2.类名、方法名混淆 3.程序结构混淆加密 4.反调试、反注入等一些主动保护策略 二 代码混淆步骤 1. 选择要混淆保护的ipa文件 2. 选择要混淆的类名称 3. 选择要混淆保护的函数&#xff0c;方法 4. 配置签名证书 5. 混淆和测…

centos7安装Nexus(Maven私服)与配置使用教程

之前有位大佬问我&#xff0c;他说有个第三方的Jar包&#xff0c;在idea导出库中使用&#xff0c;现在要部署上线测试&#xff0c;要如何导进去打包。 我说&#xff0c;不用那么麻烦&#xff0c;搞个Nexus私服&#xff0c;将Jar上传上去&#xff0c;然后配置Maven的setting文件…

现货黄金靠谱吗

现货黄金是一种相当不错的黄金投资方式&#xff0c;它通过紧密跟踪伦敦市场上黄金现货的价格走势&#xff0c;为投资者提供了捕捉差价的机会&#xff0c;而且在交易平台的帮助下&#xff0c;投资者可以获得很高的资金杠杆&#xff0c;因此即使只是抓住了一点点的行情波动&#…

01_ddim_inversion_CN

DDIM反转 设置 # !pip install -q transformers diffusers accelerateimport torch import requests import torch.nn as nn import torch.nn.functional as F from PIL import Image from io import BytesIO from tqdm.auto import tqdm from matplotlib import pyplot as p…

链表练习题

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

时间序列预测实战(十一)用SCINet实现滚动预测功能(附代码+数据集+原理介绍)

论文地址->SCINet官方论文地址 官方代码地址-> 官方代码下载地址 个人整理的代码地址->免费分享给大家创作不易请大家给文章点点赞 一、本文介绍 这篇文章给大家带来的是关于SCINet实现时间序列滚动预测功能的讲解&#xff0c;SCINet是样本卷积交换网络的缩写(Sam…