MySQL实现事务隔离的秘诀之锁

在MySQL中,有多种锁类型,我们先了解三种概念的锁,以便对接下来的内容有更好理解。

  • 表级锁(Table Lock):对整个表加锁,其他事务无法修改或读取该表的数据,但可以对其他表进行操作。
  • 页级锁(Page Lock):对数据页(通常是连续的几个行)加锁,控制并发事务对该页的访问。适用于数据较大且并发量较高的场景。
  • 行级锁(Row Lock):对单个行加锁,只锁定需要修改的数据行,其他行可以被同时修改或读取。并发性高,但锁管理较复杂。

一般来说,锁的粒度越大,性能就越差。因为粒度一大,那么发生竞争的可能性就越大,进入锁等待的概率也越大。

例如MyISAM引擎主要使用表锁设计,因此它的并发插入性能显然会很慢,因为每次插入都要加表锁,其他对此表进行操作的事务都会受到影响。而SQL Server起初是侧重于页锁,不过后续开始支持行级锁,但因为设计的缘故导致锁的资源很稀有,锁越多开销越大,最后促成锁升级变为表锁。

而InnoDB主要采用行级锁,且行级锁没有相关额外的开销,能够获得很好的并发性。

innoDB的三种行级锁就是本文的重点:行锁(Record Lock)、间隙锁(Gap Lock)、临键锁(Next-Key Lock)。

记录锁(Record Lock)

InnoDB的存储上是一颗聚簇索引树,因此,innoDB的所谓行锁,实际上就是在索引的节点上加锁。记录锁可以防止多个会话同时修改同一条记录,从而保证数据的一致性。

间隙锁(Gap Lock)

用来锁住一个范围内的间隙(即两个索引值之间的空隙),但不包括索引记录本身。

一般情况下,间隙锁是在使用范围查询或者使用唯一索引进行插入时自动创建的。在可重复读(REPEATABLE READ)或者串行化(SERIALIZABLE)的隔离级别下,MySQL会自动创建间隙锁。

间隙锁的存在可以防止幻读问题的产生。由于间隙锁会限制一定范围内的插入操作,避免了其他事务在该范围内插入新的记录,从而保证了一致性。

需要注意的是,间隙锁只锁住范围,并不锁记录本身。

像上图,(E-F)表示锁住E-F之间的记录,但E、F本身并不加锁,如果此时有另外一个事务操作E、F记录是可以成功的,但是如果是在E和F之间插入数据,则会失败。

比较特殊的,由于此时E是最小值,G是最大值,当想锁住比E小的范围时,用(-∞,E)表示;当想锁住比G大的范围时,用(G,+∞)表示。

临键锁

MySQL的临键锁(Next-Key Locks)是一种用于保护事务并发操作的锁机制。它结合了记录锁和间隙锁,能够实现在并发环境下防止幻读的效果。

临键锁的工作原理如下:

  1. 当事务对一个记录进行读取或写入操作时,会对该记录加上记录锁(行锁)。
  2. 若事务需要对一个范围进行操作(比如读取一段记录或者插入新记录),会对这个范围加上间隙锁(区间锁)。
  3. 锁的释放顺序与加锁顺序相反,即先释放间隙锁再释放记录锁。

大白话速记就是:临键锁=记录锁+间隙锁,左开右闭(不锁左边,锁右边)。

临键锁的作用如下:

  1. 防止幻读:在RR(可重复读)隔离级别下,临键锁会对查询范围的间隙进行加锁,以防止其他事务在范围内插入新记录,从而导致幻读现象。
  2. 提高并发度:临键锁的可精确加锁范围带来了更高的并发度,避免了使用传统锁(如表锁、页锁)时的大范围加锁。

不得不多嘴一句,这个临键锁的命名真是太抽象了,刚开始知道的时候,无论如何也不能通过这个名称知道,这是个什么实现。

看到这,可能有人比较疑惑,前面提到的ReadView的存在看起来已经解决了事务隔离,怎么还会有锁的存在?

事实上,ReadView可以理解为第一道关卡,类似于布隆过滤器,如果满足不了ReadView规则的,一定满足不了锁规则;如果满足了ReadView,不一定满足锁。ReadView更多只是从「读」的角度触发,提供一种快速判读的机制,但是解决不了互相写冲突的问题!

因此,锁是一种更为底层同时逻辑偏重的保证机制。

总结:

  • InnoDB有三种锁:记录锁、间隙锁、临键锁。
  • 记录锁只锁住某个具体节点;间隙锁锁住区间但不包含记录本身;临键锁=记录锁+间隙锁,主要用来解决不可重复读的问题

上一篇:诚意满满之MySQL实现事务隔离的秘诀:锁与MVCC

刚好讲到了Record Lock、Gap Lock和Next-Key Lock,那下一篇便讲一讲在实际工作中容易遇到的,如何排查和解决死锁的问题。

欢迎关注~

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【研发管理】产品经理-基础认知

导读:产品经理(Product Manager)是一个负责产品的全周期管理的职位,他们不仅参与产品的设计、开发、推广和销售,还涉及到产品的市场调研、用户需求分析、竞争分析、产品规划、产品测试以及后续的产品迭代等多个环节。产…

C语言-strtok(切片的使用)

strtok(切片的使用) 使用规则 使用的基本情况 strcpy 第二次调用的时候传的是空指针 所以打印出来的是 每一次调用函数都会把当前函数的地址记住 所以二次调用的时候 传的是null 连起始位置都不传了 只是传null 但是需要知道的是 当知道三段 你调用第…

MySQL语法分类 DDL(1)

DDL(1)(操作数据库、表) 数据库操作(CRUD) C(Create):创建 //指定字符集创建 create database db_1 character set utf8;//避免重复创建数据库报错可以用一下命令 create database if not exists db_1 character set utf8;R(Retrieve):查询 //查询所…

由浅到深认识C语言(6):变量的存储类型

该文章Github地址:https://github.com/AntonyCheng/c-notes 在此介绍一下作者开源的SpringBoot项目初始化模板(Github仓库地址:https://github.com/AntonyCheng/spring-boot-init-template & CSDN文章地址:https://blog.csdn…

flowable-ui部署

版本 java: java8+tomcat: apache-tomcat-9.0.87flowable: flowable-6.8.1mysql驱动: mysql-connector-java-8.0.30.jar 注意:版本一定要对,否则启动报错执行数据库脚本 创建数据库flowable执行脚本,脚本位于解压flowable-6.8.1.zip后的flowable-6.8.1/database/create/all/…

网络编程套接字——实现简单的UDP网络程序

目录 1、预备知识 1.1、认识端口号 1.2、端口号 vs 进程pid 1.3、认识TCP协议 1.4、认识UDP协议 1.5、网络字节序 2、socket编程接口 2.1、socket常见API 2.2、sockaddr结构 3、实现一个简易的UDP服务器和客户端通信 log.hpp UdpServer.hpp UdpClient.cc Main.cc…

Ubuntu 20.04 系统如何优雅地安装NCL?

一、什么是NCL? NCAR Command Language(NCL)是由美国大气研究中心(NCAR)推出的一款用于科学数据计算和可视化的免费软件。 它有着非常强大的文件输入和输出功能,可读写netCDF-3、netCDF-4 classic、HDF4、b…

【全开源】JAVA匿名情侣假装情侣系统源码支持微信小程序+微信公众号+H5

一、功能介绍 匹配情侣、聊天功能、匹配记录 会员功能、我的团队、合伙代理 修改个人资料 我们技术使用JAVA后台服务 前后端分离 springbootmybatisplusmysql 用户端 uniapp(vue语法)管理后台 vueelementUi 适配小程序H5公众号,一套源码…

STM32(TIM定时器中断)

理论知识 定时器定时中断 接线图 定时器工作配置步骤 定时中断和内外时钟源选择 定时器中需要使用的函数 程序实现效果: void TIM_DeInit(TIM_TypeDef* TIMx); **// 恢复定时器的缺省配置**void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef*TIM…

261:vue+openlayers 使用setRotation旋转地图

第261个 点击查看专栏目录 本示例介绍演示如何在vue+openlayers中使用setRotation旋转地图。setRotation是view的一个方法,旋转的内容是弧度,这里设置的角度需要将其换算为弧度,即 x*Math.PI/180. 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果 文章目…

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:WaterFlow)

瀑布流容器,由“行”和“列”分割的单元格所组成,通过容器自身的排列规则,将不同大小的“项目”自上而下,如瀑布般紧密布局。 说明: 该组件从API Version 9 开始支持。后续版本如有新增内容,则采用上角标单…

神经网络中激活函数的绘制——阶跃函数、sigmoid函数、ReLU函数

一、阶跃函数 import numpy as np import matplotlib.pylab as plt def step_function(x):return np.array(x>0)x np.arange(-5.0,5.0,0.1) y step_function(x) plt.plot(x, y) plt.ylim(-0.1, 1.1) plt.show() 二、sigmoid函数 import numpy as np import matplotlib.p…

194 基于matlab的日历GUI制作

基于matlab的日历GUI制作,可实时显示当前的日期和时间,精确到秒。非常漂亮,也很基础,学习GUI的不错程序,程序已调通,可直接运行。 194 matlab 日历制作 GUI可视化 - 小红书 (xiaohongshu.com)

JS第一阶段2

文章目录 1. 对象创建对象的三种方式new关键字遍历对象属性 2. JS内置对象2.1查文档2.2Math对象随机数 2.3日期对象Date 使用日期格式化获取日期的总的毫秒形式倒计时秒杀案例 2.4数组对象检测是否是数组添加删除数组元素的方法数组排序数组索引方法数组去重案例数组转换为字符…

Visual Studio配置libtorch(cuda安装一步到位)

Visual Studio配置libtorch visual Studio安装cuDNN安装CUDAToolkit安装libtorch下载Visual Studio配置libtorch(cuda版本配置) visual Studio安装 visual Studio点击安装 具体的安装和配置过程这里就不进行细讲了,可以参考我这篇博客Visual Studio配置OpenCV(保姆…

数据结构的概念大合集01(含数据结构的基本定义,算法及其描述)

概念大合集01 1、数据结构基础的定义2、数据结构2.1 数据元素之间关系的集合2.2数据结构的三要素2.2.1数据的逻辑结构2.2.2数据的存储(物理)结构2.2.3数据的运算 3、数据类型4、抽象数据类型类型(ADT)5、算法及其描述5.1算法的5个…

R语言实现中介分析(1)

中介分析,也称为介导分析,是统计学中的一种方法,它用于评估一个或多个中介变量(也称为中间变量)在自变量和因变量之间关系中所起的作用。换句话说,中介分析用于探索自变量如何通过中介变量影响因变量的机制…

将 OpenCV 与 Eclipse 结合使用(插件 CDT)

返回:OpenCV系列文章目录(持续更新中......) 上一篇:将OpenCV与gcc和CMake结合使用 下一篇:OpenCV4.9.0在windows系统下的安装 警告: 本教程可以包含过时的信息。 先决条件 两种方式,一种…

【IC设计】Verilog线性序列机点灯案例(二)(小梅哥课程)

文章目录 该系列目录:设计目标设计思路RTL 及 Testbench仿真结果存在的问题?改善后的代码RTL代码testbench代码 仿真结果 案例和代码来自小梅哥课程,本人仅对知识点做做笔记,如有学习需要请支持官方正版。 该系列目录:…

接雨水-热题 100?-Lua 中文代码解题第4题

接雨水-热题 100?-Lua 中文代码解题第4题 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 示例 1: 输入:height [0,1,0,2,1,0,1,3,2,1,2,1] 输出:6 解释…