MySQL是如何实现事务的隔离级别

news2024/11/24 23:00:32

MySQL是如何实现事务的隔离级别 - 游生 - 博客园

摘要

本文旨在了解MySQL InnoDB引擎如何支持事务的隔离级别。

文章主要内容分两个部分。

第一部分阐述数据库的并发问题以及为之产生的ANSI SQL 标准隔离级别。

第二部分根据 MySQL 官方文档解释 InnoDB 是如何支持这些隔离级别的。

数据库事务的并发问题

ANSI SQL 隔离级别的定义是来源于三个异象问题,ANSI SQL在权衡系统的可靠性和性能之间定义了不同的级别。所以这里先介绍主流的三个并发问题是什么。

读异象 (read phenomena)

  • 脏读 (dirty read)
    • 一个事务读取到了另一个事务更新但未提交的数据。当另一个事务回滚或者再次修改,就会读取到脏数据
  • 不可重复读 (non-repeatable read / Fuzzy Read)
    • 现象为一个事务多次同样读取数据的操作其结果不一致。例如读取时有其他事务提交了修改
  • 幻读 (phantom)
    • 在多次同样的查询操作下,后面的查询出现了新行的数据。
    • 例如在执行多次查询的时候,其他事务插入了一个新行或者修改了某行数据使得能匹配上Where条件,那么后一次查询必然将查询到这个新数据(也就感觉出现了幻觉,莫名其妙多出了一行)
    • 不可重复读和幻读其实类似,但是幻读偏向于查询新增数据(所以专门弄了间隙锁来防止幻读),不可重复读则是修改数据。

Def: The so-called phantom problem occurs within a transaction when the same query produces different sets of rows at different times. For example, if a SELECT is executed twice, but returns a row the second time that was not returned the first time, the row is a “phantom” row.

    • 注:幻象 (Phantom) ,幻读 (Phantom Read) ,幻象问题 (Phantom Problem) 都是一个表述。
  • 总结:上面介绍的三个读并发问题,其本质都是一个事务在读其他事务修改过的数据。

标准事务隔离级别

  • 因为事务在并发执行的过程中会存在相互干扰,需要有隔离性的保障,故引入事务隔离级别规范,以平衡操作的性能、可靠和一致

ANSI SQL下规定的隔离级别(1992 - 很老的标准了)

  1. 未提交读 - Read Uncommited
    • 风险挺高,但是如果只是存粹的读操作可以推荐使用(MyISAM也挺香呀)
  1. 已提交读 - Read Commited(互联网主流默认使用的隔离级别)
    • 事务无法看见其他未提交事务的修改
  1. 可重复读 - Repeatable Read (MySQL 默认)
    • 只读事务开始时的快照数据
  1. 可序列化 - Serializable
  • ANSI SQL规定的隔离级别其实还是根据主流存在的数据库并发问题来定义的,每个隔离级别来解决不同的问题。

如果细分继续细分不同的并发问题,隔离级别还能更加细化。

 


MySQL是如何支持不同隔离级别的

知识准备(术语解释)

  • 一致性读取 (consistent read)
    • 事务在进行读操作时,使用的是事务开始时的行快照数据,这样就不用担心读到其他其他事务修改的数据。
    • 在[可重复读]下,事务快照是基于第一次读操作的快照(通过undo log 回溯)
    • 在[可提交读]下,每一次一致性读操作都会重置快照
    • 优点:不上锁,允许其他事务进行修改
  • 半一致性读取 (semi-consistent read)
    • 即UPDATE语句中的读/匹配操作,当UPDATE语句执行的时候,InnoDB会取最后一次提交到MySQL的数据来进行 Where 子句中的匹配。
      • 如果匹配上了(也就是要更新),那就重读该行并加锁(或等待加锁)
        • todo 为什么要重读该行不是很理解,直接用那条数据不就好了
    • 仅用于[可提交读]隔离级别
    • 个人理解其实就是一致性读取在[可提交读]隔离级别下 UPDATE的表现
  • 锁定读 (locking read)
    • 即加锁的查询语句
    • E.g SELECT ... FOR UPDATE | SELECT ... FOR SHARE
  • 行锁 (record lock) : 即锁定索引记录的锁,即使没有索引也会找到对应行记录锁主键哦
  • 间隙锁 (gap lock) : 锁在了两条索引记录之间的锁,或者(无穷小,某索引)/(某索引,无穷大),他们锁住的是一个范围,且不同的间隙锁不互斥,他们排斥的只是在锁范围内的插入操作
    • mark: R.C 隔离级别下是被禁用的
  • next-key lock : 行锁和间隙锁的组合实现

未提交读 - Read Uncommited

  • SELECT 语句采用的无锁策略,也就更容易产生脏读

已提交读 - Read Commited

  • 该隔离级别下的一致性读取,读的都是最新版的快照,每次读快照都会被重置成最新

Each consistent read, even within the same transaction, sets and reads its own fresh snapshot.

  • 对于Locking Reads、UPDATE、DELETE 语句,InnoDB的锁策略是只锁索引记录,并没有用间隙锁来锁范围,所以容易产生幻读问题

特别的对于 R.C 隔离级别有以下变动

  • 对于UPDATE语句,如果行已经被加锁了,InnoDB会使用 “semi-consistent”read,来读取快照中最新的值(而不是最原始的快照)来进行 WHERE 匹配更新。(也就是说 UPDATE 也采用 R.C 特供版一致性读取)
  • 对于UPDATE或 DELETE语句,InnoDB仅对其更新或删除的行持有锁。MySQL评估WHERE条件后,将释放不匹配行的记录锁。这大大降低了死锁的可能性。
    • 比如扫表过程中,扫到这行不是要修改的,那么就释放锁,要改的就一直加锁直到事务结束
    • R.R 级别下则不会释放

关于这个“semi-consistent” read

  • 他读取的是最后一次提交到MySQL的版本,而不是快照中最早读的那个版本
  • 优点:MySQL可以判断当前的更新操作是否符合Where条件,如果不匹配就不用更新了,也就节省了一次写操作,如果匹配就重新读取尝试加锁
  • 缺点:如果都采用一致性读consistent read,读取都是最早事务的快照,就不会产生幻象问题了(Phantom Problem);但是采用了半一致性,两次查询的结果可能会不一致。

可重复读 - Repeatable Read

  • 采用一致性读取,同事务中的每次读取都取第一次读的快照。(R.R 版一致性读取)

Consistent reads within the same transaction read the snapshot established by the first read.

  • 对于 locking reads,UPDATE,DELETE ,其加锁策略取决于是否是唯一索引唯一条件查询
    • 唯一索引配合唯一查询条件,引擎只锁定那条索引记录,不锁间隙
    • 其他场景,引擎使用Gap Lock 或 Next-Record Lock来锁定扫描的索引范围,以阻止其他事务插入新行到该间隙

串行化 - Serializable

  • InnoDB 默默的把所有纯 SELECT 语句都转成了 SELECT ... FOR SHARE ,也就默认都加读锁

小结

  • InnoDB 是依赖于不同的锁策略实现了不同隔离级别的要求
  • R.C 隔离级别使用了当前读 (R.C 下的一致性读取) 且 禁用了间隙锁
  • 理论上 R.R 隔离级别下因为使用了一致性读和间隙锁是不会产生的幻读问题的,所以标准可能有点老了
    • todo MySQL在介绍幻读的时候说 R.R 下面会有幻读,但又没有实际的例子,很难让人信服。(除非这个也算:两次查询前一次是普通读,后一次是锁定读)

扩展

  • 在介绍 ANSI 隔离级别标准的时候,提到了ANSI标准是根据主流的三个并发问题来对症下药的,但其实仍然有一些并发问题被 ANSI 标准给默认忽略或者说就不关心了,比如典型的脏读和丢失修改。更详细的可以参考下图(1995)

 

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

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

相关文章

关于python中自带的类似postman的工具

关于python中自带的类似postman的工具 1.新建一个http 请求: 2.添加请求方式 2.1程序运行 验证数据的运行: 1.post数据添加验证

打造无证服务化:这个政务服务平台有点不一样

摘要:华为云携手深圳市华傲数据技术有限公司针对“数字政府建设”与“数字经济发展”两大场景,打造华傲可信政务区块链解决方案。本文分享自华为云社区《华为云携手华傲数据打造“无证服务”政务服务平台》,作者:灰灰哒 。 当前&…

xray扫描器的使用长亭xray被动扫描

长亭xray被动扫描为了实现点到哪里扫到哪里,用长亭xray配合burp suite插件 插件名为Passive Scan Client GitHub - lilifengcode/Burpsuite-Plugins-Usage: Burpsuite-Plugins-Usage 就用默认端口1664就行,把浏览器代理设成127.0.01 : 1664…

【Pandas数据处理100例】(八十七):Pandas使用get_dummies构建哑变量

前言 大家好,我是阿光。 本专栏整理了《Pandas数据分析处理》,内包含了各种常见的数据处理,以及Pandas内置函数的使用方法,帮助我们快速便捷的处理表格数据。 正在更新中~ ✨ 🚨 我的项目环境: 平台:Windows10语言环境:python3.7编译器:PyCharmPandas版本:1.3.5N…

<学习笔记>从零开始自学Python-之-web应用框架Django( 十一)用户系统和身份验证

用户系统是现代网站的重要组成部分,对用户进行分组权限管理是非常必要的。 Django内置了一套用户和身份验证系统,不用太多代码开发就可以使用这个系统。 Django 的身份验证系统包括: • 用户 • 权限:二元(是或否&…

Unity游戏Mod/插件制作教程05 - 插件实例2: 简单功能实现

这一次的教程进行一个小小的功能实现,完整的制作一个插件。以Mirror这个游戏为例,插件的目标是当玩家按下空格时,有一定概率为玩家增加金钱,或者扣除玩家金钱。概率、增加的金钱、扣除的金钱都由配置文件决定。 使用dnSpy查找金钱…

【SQL】数据库事务

【SQL】数据库事务事物的ACID特性事务的状态显式事务隐式事务事务的使用举例SQL中的四种隔离级别MySQL中的隔离级别如何设置事务的隔离级别innodb默认支持事务事务是一组逻辑操作单元,使数据从一种状态转变到另一种状态事物的ACID特性 原子性(atomicity…

Java搭建宝塔部署实战毕设项目springboot车险理赔管理系统源码

大家好啊,我是测评君,欢迎来到web测评。 本期给大家带来一套Java开发的毕业设计项目springboot车险理赔管理系统源码。 技术架构 技术框架:SpringBoot mybatis bootstrap jquery mysql5.7运行环境:jdk8 nginx1.20 tomcat9 …

QT学习笔记(六)——QT弹出对话框并在主窗口调用对话框的信息

QT弹出对话框并在主窗口调用对话框的信息,显示影像 最近封控,大部分时间都在自己学习写代码,有点feel 了哈,自己摸出来一个简单的qt 界面,也实现了自己想要的功能。本篇博客主要记录一下,如何弹出对话框&a…

[附源码]SSM计算机毕业设计疫情期间物资分派管理系统JAVA

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

@Accessors 注解作用

文章目录前言一、Accessors 源码二、Accessors 属性说明1、fluent 属性2、chain 属性3、prefix 属性前言 在最近的工作中,看到 Accessors(chain true) 这样的注解,上网查询了下,他是 lombok 插件包中的一个注解,那么它是什么意思…

如何快速实现一个颜色选择器

在做前端界面开发的时候,遇到需要改变颜色的需求,就需要使用颜色选择器。 针对这个问题,第一想法,自然是H5提供了input color,可以实现。但不出意外的,IE并不支持。而且,chrome的实现方式和fire…

[附源码]Python计算机毕业设计Django个人博客系统

项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等等。 环境需要 1.运行环境:最好是python3.7.7,…

【java】输入输出流

文章目录标准输入流标准输出流字节打印流字符打印流案例--复制java文件(文件打印流版本)对象序列化流序列化流反序列化流serialVersionID&transientProperties作为Map集合的使用Properties作为集合的特有方法Properties与IO流相结合的方法案例--游戏…

必备模块知识——超声波传感器

一、超声波传感器 1、什么是超声波 人们能听到声音是由于物体振动产生的,它的频率在20HZ-20KHZ范围内,超过20KHZ称为超声波,低于20HZ的称为次声波。常用的超声波频率为几十KHZ-几十MHZ。 2、什么是超声波传感器(常用的HC-SR04超…

基于PHP+MySQL教室预约管理系统的设计与实现

随着我国国民教育的提高,大学生的数量一直在不断的增加,根据网络资料的查询,发现2012年的大学生人数为600万,这是一个不小的数量,说明了我国教育的进步是巨大的。但是问题也随之产生,每年如此多的大学生就需要大学不断的扩建,可是还是不能满足如此多的学生对教室的使用,所以如何…

【学习笔记】深度学习入门:基于Python的理论与实现-与学习相关的技巧

CONTENTS六、与学习相关的技巧6.1 参数的更新6.2 权重的初始值6.3 Batch Normalization6.4 正则化6.5 超参数的验证六、与学习相关的技巧 6.1 参数的更新 神经网络的学习的目的是找到使损失函数的值尽可能小的参数。这是寻找最优参数的问题,解决这个问题的过程称为…

YOLOv7(目标检测)数据集、训练、推理过程

一、环境安装: pip install -r requirements.txt pip install torch1.8.2cu111 torchvision0.9.2cu111 torchaudio0.8.2 -f https://download.pytorch.org/whl/lts/1.8/torch_lts.html -i https://pypi.tuna.tsinghua.edu.cn/simple二、修改配置环境 直接看下面…

[附源码]SSM计算机毕业设计血库管理系统JAVA

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

JavaScript -- 03. 运算符介绍

文章目录运算符1 算数运算符1.1 基础符号1.2 自动类型转换2 赋值运算符3 一元4 自增和自减4.1 自增运算符4.2 -- 自减运算符5 逻辑运算符5.1 逻辑非5.2 逻辑与5.3 逻辑或6 关系运算符7 相等运算符7.1 7.2 7.3 !7.4 !8 条件运算符(三元表达式)9 运算符的…