Mysql事务隔离机制

2023-10-27

SQL隔离机制:

所谓隔离机制,指的是读与写之间的隔离,指的是在多事务并行的时候,A事务的读与B事务的写之间的隔离,也就是说B事务的写对A事务的可见性。

多事务并发运行的时候,同时读写一个数据,可能会出现脏写、脏读、不可重复读、幻读几个问题。

脏写:

两个事务都更新一个数据,结果A事务回滚了,把B事务更新的数据回滚没了。

脏读:

A事务读取到B事务没有提交的但修改了的数据,结果B事务回滚了,A事务下次就读不到了。

不可重复读:

A事务运行期间,B事务修改了一条数据,并且提交了,A事务前后对这条数据读取到的值不一样。

幻读:

A事务进行范围查询,B事务插入了新的几条数据,并且提交了,A事务前后范围查询查到的结果不一样。

针对以上问题,才有了RU、RC、RR和串行化四个隔离级别。

RU:

Read Uncommited,读未提交,就是可以读到其他事务修改了但没有提交的数据。

RC:

Read Commited,读已提交,可以读到其他事务已提交的数据,可以避免脏读、脏写。

RR:

Read Repeated,可重复读,不会读到别的已经提交事务修改的数据,可以避免脏读、脏写、不可重复读。

串行化:

让所有事务都串行执行,可以避免所有问题,但是效率很低,会大大降低并发。

MYSQL隔离机制:

设置隔离级别:SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL level

level值可以是:REPEATABLE READ, READ COMMITED, READ UNCOMMITTED, SERIALIZABLE

Mysql默认的RR隔离级别,使用MVCC机制,避免了脏写、脏读、不可重复读、幻读的问题的。

所谓MVCC机制,是基于undo log多版本链条 + ReadView机制来实现的。

MVCC机制:

所谓MVCC机制,就是多版本并发控制机制,只要是多线程访问同一份数据,都可以使用这种多版本并发控制机制。基于undo版本链 + ReadView机制 来实现的

Undo log版本链:

其实我们每条数据都有两个隐藏字段,一个是trx_id,一个是roll_pointer,这个trx_id就是最近一次更新这条数据的事务id,roll_pointer就是指向更新这个事务之前生成的undo log。

举个例子:

假设有一个事务A(id=50),插入了一条数据,此时这条数据的值以及隐藏字段的值如下图所示,插入的值为值A,因为事务的id是50,所以trx_id等于50,roll_pointer指向一个空的undo log,因为之前这条数据是没有的。

接着假设事务B跑过来修改了一下这条数据的值,把值改成了值B,事务的id是58,那么此时更新之前会生成一个undo log记录之前的值,然后会让roll_pointer指向这个实际的undo log回滚日志。

接着假设事务C又来修改了一下这个值为值C,它的事务id时69,此时会把数据行里的trx_id改为69,然后生成一条undo log,记录及之前事务B修改的那个值,然后roll_pointer指向了本次修改之前生成的undo log,也就是记录了事务B修改的那个undo log。

总结:

每个事务修改一行数据的值,都会更新隐藏字段trx_id和roll_pointer,同时之前多个快照对应的undo log会通过roll_pointer指针串联起来,形成一个版本链,也就是undo log版本链。

ReadView机制:

执行一个事务的时候,就会生成一个ReadView,里面有四个比较关键的东西:

一个是m_ids,这个就是说事务开启那一刻有哪些事务在Mysql里面执行还没有提交的;

一个是min_trx_id,就是m_ids里最小的事务id的值;

一个是max_trx_id,就是此刻mysql下一个要生成的事务id,就是最大事务id;

一个是creator_trx_id,就是你这个事务的id。

举了例子:

假设原来数据库里就有一行数据,事务id是32,如下图所示:

接着呢,此时两个事务并发过来执行了,一个是事务A(id=45),一个是事务B(id=59),事务B是要去更新这条数据的,事务A是要去读取这条数据的,此时两个事务如下图所示:

现在事务A直接开启一个ReadView,这个ReadView里的m_ids就包含了事务A和事务B的两个id,45和59,然后min_trx_id就是45,max_trx_id就是60,creator_trx_id就是45,就是事务A自己。

这个时候事务A第一次查询这行数据,会走一个判断,就是判断当前这行数据的trx_id是否小于ReadView的min_trx_id,此时发现trx_id=32,小于ReadView里的min_trx_id就是45的,说明事务开启前这行数据早就提交了,所以此时可以查看到这行数据,如下图所示:

接着事务B开始动手了,它把这行数据的值修改为了值B,然后这行数据的trx_id设置为了自己的id,也就是59,同时roll_pointer指向了修改之前生成的一个undo log,接着这个事务B就提交了,如下图所示:

这个时候,事务A再次查询,此时查询的时候,发现此时数据行里的trx_id=59,大于它的ReadView里的min_trx_id(45),同时小于ReadView里的max_trx_id(60)的,说明这条数据的事务,很可能就跟自己差不多同时开启的,于是会看一下这个trx_id=59是否在ReadView的m_ids列表(包含45,59)里,发现在列表里,这个修改数据的事务是跟自己同一时段并发执行然后提交的,所以这行数据是不能查询的。

然后顺着这条数据的roll_pointer顺着undo log链往下找,找到最近的一条undo log,trx_id=32,此时发现trx_id=32小于ReadView里的min_trx_id(45),说明这个undo log版本必然是在事务A开启之前就执行并提交了的,然后读取该undo log里快照值。

接着假设事务A自己更新了这条数据的值,改成值A,trx_id修改为45,同时保存之前事务B修改的值的快照,如下图所示:

此时事务A来查看这条数据,发现trx_id=45,等于自己ReadView里的creator_trx_id(45),说明这行数据是自己修改的,可以查看。如下图:

接着在事务A执行的过程中,突然开启了一个事务C,这个事务C的id是78,然后它更新了那行数据的值为值C,还提交了,如下图所示:

这个时候,事务A再去查询,发现当前数据的trx_id=78,大于自己的ReadView中的max_trx_id(60),说明了有个事务在事务A开启之后,更新了数据并提交了。

此时事务A就会顺着undo log版本链往下找,找到自己修改的那个版本,然后读出来,如下图:

总结:

通过undo log多版本链条,加上你开启事务时候生成的ReadView,然后查询的时候,根据ReadView的判断机制,你就知道应该读取那个版本的数据。

实现机制:

1、Undo log 多版本链条:

根据undo log 多版本链条进行查找,找到符合条件的版本数据;

2、ReadView:

如果trx_id < min_trx_id:在你事务开启那一刻之前就已提交的事务更新的版本

如果trx_id > max_trx_id:在你事务开启那一刻之后开启的事务更新的版本

如果trx_id = creator_trx_id:是你所在的事务更新的版本

如果trx_id 在m_ids列表中:是你事务开启那一刻已开启但未提交的事务更新的版本

实现效果:

  1. 可以保证你只能读到你事务开启之前已提交更新的值,还有就是自己事务更新的值;
  2. 在你事务开启之前,就有别的事务正在运行,然后你事务开启之后,别的事务更新提交了的值,你是读不到的;
  3. 你事务开启之后,比你晚开启的事务更新提交了的值,你也是读不到的。

RC隔离级别下的MVCC:

同一个事务中的每次查询都会新生成一个ReadView。

那么如果在你这次查询之前,有事务修改了数据还提交了,你这次查询生成的ReadView里,那个m_ids列表当然不包括这个已经提交的事务了,既然m_ids列表不包含已经提交的事务了,就可以读取到人家修改的值了。

RR隔离级别下的MVCC:

同一个事务中的每次查询都使用同一个ReadView,就是事务开启那个时刻的ReadView。

Mysql内部架构_jerry_dyy的博客-CSDN博客

Mysql存储模型_jerry_dyy的博客-CSDN博客

InnoDB内部架构_jerry_dyy的博客-CSDN博客

Buffer Pool 核心原理_jerry_dyy的博客-CSDN博客

Buffer Pool生产实践_jerry_dyy的博客-CSDN博客

Mysql事务隔离机制_jerry_dyy的博客-CSDN博客

Mysql的锁机制_jerry_dyy的博客-CSDN博客

Mysql的索引深度讲解_jerry_dyy的博客-CSDN博客

Mysql索引的使用_jerry_dyy的博客-CSDN博客

SQL语句的执行计划_jerry_dyy的博客-CSDN博客_sql语句的执行计划

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Mysql事务隔离机制 的相关文章

  • Sql:计算随时间的增长

    我几周前发布了这个问题 但我认为我没有清楚地提出这个问题 因为我得到的答案不是我想要的 我认为最好重新开始 我正在尝试查询数据库以检索一段时间内唯一条目的数量 数据看起来像这样 Day UserID 1 A 1 B 2 B 3 A 4 B
  • 本地数据库缓存的最佳实践?

    我正在开发一个应用程序 该应用程序的部分内容依赖于 MySQL 数据库 在某些情况下 应用程序将在互联网连接 UMTS 有限的环境中运行 特别是延迟较高的环境 应用程序的用户能够登录 并且应用程序用户界面的大部分内容都是从 MySQL 数据
  • 基本表创建 fpdf

    我找不到使用 fpdf 制作表格并从 mysql 数据库获取数据的合适教程 我只是想知道如何创建一个 我在网上尝试示例时遇到了很多错误 例如 我有 名字 中间名 姓氏 年龄 和 电子邮件 列 如何使用 fpdf 创建表格并回显数据库中的条目
  • 我可以在一个查询中更新/选择表吗?

    我需要在查看页面时选择数据并更新 视图 列 有没有一种方法可以在一个查询中执行此操作 或者我是否必须使用不同的查询 如果您不想 不需要使用事务 则可以创建一个存储过程 该过程首先更新视图计数 然后选择值并将其返回给用户
  • 在 PHP 中将十进制/双精度/浮点值与 PDO 绑定的最佳方法是什么?

    看来类常量只涵盖PDO PARAM BOOL PDO PARAM INT and PDO PARAM STR用于绑定 您只是将十进制 浮点 双精度值绑定为字符串还是有更好的方法来处理它们 MySQLi 允许使用 d 类型表示 double
  • 哪个是识别关系或非识别关系中的子表?

    在表之间的识别和非识别关系的上下文中 MySQL 文档大量将表称为父表和子表 如何判断哪个表是父表 哪个表是子表 子表 A K A 弱实体 http en wikipedia org wiki Weak entity 是一个表 其主键属性d
  • 通过将行旋转为动态数量的列来在 MySQL 中创建摘要视图

    我在 MySQL 中有一个表 其中包含以下字段 id company name year state 同一客户和年份有多行 以下是数据示例 id company name year state 1 companyA 2008 1 2 com
  • INNER JOIN 可用作 SELECT,但不能用作 DELETE [重复]

    这个问题在这里已经有答案了 为什么这个有语法错误 DELETE FROM print mailing request pmr INNER JOIN person p ON p id pmr person AND p email LIKE T
  • 在 MySQL 数据库上使用版本控制 (Git)

    我是一名 WordPress 设计师 开发人员 越来越多地使用版本控制 特别是 Git 尽管我确实在某些项目中使用 SVN 我目前正在使用 Beanstalk 作为我的远程仓库 将所有 WordPress 文件添加到我的存储库中是没有问题的
  • 在 MySQL 中创建布尔列并将 false 作为默认值?

    我想在 MySQL 中创建一个表boolean默认值为的列false 但它默认接受 NULL 你必须指定0 意思是假 或1 意思是 true 作为默认值 这是一个例子 create table mytable mybool boolean
  • MYSql 前 10 名及其他总计

    我的查询运行良好 但我只需要前 10 个供应商 然后我需要将所有剩余的总计放在 所有其他 行中 如果没有单独的查询 我该如何做到这一点LIMIT 10 18446744073709551615 SELECT VENDOR fullname
  • 错误代码 13,SELECT INTO OUTFILE 问题

    我试图了解使用 INTO OUTFILE 命令时不断遇到问题的原因 我总是收到这个错误 ERROR 1 HY000 Can t create write to file var www p1 txt Errcode 13 SELECT pa
  • 未知的表引擎“InnoDB”

    最近 我发现如果我有好的硬件 我可以最大限度地提高 mysql 的性能 由于我一直在使用 InnoDB 所以我在 my ini 中添加了额外的配置 以下是新添加的配置 innodb data file path ibdata1 10M au
  • mysqldb接口错误

    我对 mysqldb python 的 mysql 模块 有一个非常奇怪的问题 我有一个文件 其中包含用于在表中插入记录的查询 如果我从文件中调用函数 它就可以正常工作 但是当尝试从另一个文件调用其中一个函数时 它会抛出一个 mysql e
  • mysqldump创建空sql文件? [Windows 上的 php 和 mysql]

    我尝试转储数据库 我尝试了指定 mysqldump exe 的完整路径或仅使用 mysqldump 它仍然给我一个 0kb dumpfile sql 细节 编程语言 PHP 数据库 MySql 5 XX 操作系统 服务器 Windows S
  • MySql 复合索引

    我们使用 MySql 作为我们的数据库 以下查询在 mysql 表 大约 2500 万条记录 上运行 我在这里粘贴了两个查询 查询运行得太慢 我想知道更好的复合索引是否可以改善这种情况 你知道最好的综合指数是什么吗 并建议我这些查询是否需要
  • binary_log_types.h:没有这样的文件或目录

    我正在编译一个小型 mysql C 项目并且 遇到以下错误 C Program Files x86 MySQL MySQL Server 5 7 include mysql com h 22 30 fatal error binary lo
  • 尝试在 Mac OSX 上的 virtualenv 和 MySQL 中安装 Django CMS 时出错

    当我尝试使用 virutalenv 安装带有 MySQL 的 django CMS 时 出现以下错误 RuntimeError maximum recursion depth exceeded Users ethan Sites env b
  • 像搜索一样在mysql中包含空格

    我在某些情况下使用 mysql like 关键字时遇到问题 我的要求是这样的 首先 当我搜索时 ABC 结果应该找到ABC and ABCdef但不是xyzABCdef or xyzABC 乍一看使用起来很简单ABC 但在我搜索时的情况 h
  • 在 Java Web 应用程序中获取 DataSource 资源

    我的 context xml 文件中有以下资源标记

随机推荐

  • Redis IO 多路复用底层的实现原理

    文章目录 前言 用户空间与内核空间 PIO 和 DMA PIO DMA 缓存I O和直接I O 缓存I O的读写操作 缓存I O的优点 缓存I O的缺点 直接I O的优点 IO的访问方式 磁盘IO 网络IO 磁盘IO和网络IO对比 同步IO
  • AG表格基础滚动分页-React版本

    AG表格滚动分页文档 AG表格在使用滚动分页时 不可使用rowData属性做为数据源 传入表格 因为AG的滚动分页 使用的是特殊表模型 所有正常模型下的API有可能会失效 使用AG滚动分页时 需把正常数据模型替换成滚动分页数据模型 示例 t
  • 30天自制操作系统学习-第2天

    第二天主要学习汇编语言与Makefile入门 1 继续开发 在这里先给出作者在第二天使用nask编写代码中涉及到的寄存器概念 AX accumulator 累加寄存器 CX counter 计数寄存器 DX data 数据寄存器 BX ba
  • 反射工具类导入Excel数据到数据库

    1 工作类代码 import org apache poi hssf usermodel HSSFWorkbook import org apache poi ss usermodel import org apache poi xssf
  • ubuntu20.04换国内清华源和安装docker

    写在前面 安装好ubuntu双系统后 默认的软件更新源是国外的 在国内使用速度很慢 用 apt install xxx 安装软件时可能出现 网络不可达 你的网络需要认证吗 无法定位软件包 等错误 所以我们需要更换成国内的源 这样才能正常安装
  • c++读写文件操作

    程序的运行产生的数据都是临时数据 不能持久的保存 一旦程序运行结束数据就会被释放 在C 中对文件进行操作必须包含头文件
  • Flutter开发中插件使用

    flutter的库是以package的方式来管理的 Package 分为两种 Dart package 它只能使用 Dart 和 Flutter 提供的 API 使用纯dart语言开发 一些Dart包可能包含Flutter特定功能 因此对F
  • chatgpt赋能python:Python编程优化技巧

    Python编程优化技巧 为什么需要编程优化 Python是一种解释性语言 运行速度较慢 编写高效的Python程序是很有必要的 当我们需要处理大量数据 或者运行时间敏感的任务时 优化Python程序对于提高效率是至关重要的 怎样提高Pyt
  • 华为OD机试 C++ 【查字典】

    题目 题目 描述 给你一个 头 就是词的开始部分 和一个单词清单 你需要找出哪些单词是以这个 头 开始的 输出 所有以这个 头 开始的单词 每个单词一行 如果一个都没有 输出 1 输入 abc 4 a ab abc abcd 输出 abc
  • 项目结构的合理性

    以下仅为个人观点 如有好的建议请多多指教 1 有时为了项目以后修改 迭代 或者相似功能的开发 可能会对某些模块进行封装 近期所做的项目整体进行了自动化封装 个人认为封装过度其实是对后续业务并没有太多好处 反而造成项目随着时间的推移 业务发展
  • sessionStorage 问题

    问题描述 列表页点击进详情页的时候数据没加载到 查看前端代码 在跳转的时候取的列表页数据存到sessionStorage里面 function getCollarDetails index var rows coupon list tabl
  • jQuery 入门教程(21): jQuery UI 示例

    上篇介绍了使用jQuery UI基本工作过程 后面就逐个介绍jQuery UI库内置的UI组件 支持的拖放 动画效果等 如果你之前看过Yii Framework教程 PHP Yii Framework封装了jQuery UI组件 有兴趣的可
  • SqlServer 存储过程(生成订单)

    当在 SQL Server 中处理订单时 使用存储过程可以提供更高效和可维护的解决方案 存储过程是一组预编译的 SQL 语句 可以在数据库中执行 并且可以通过参数进行自定义 通过使用存储过程 可以将常见的业务逻辑封装起来 以便在需要时进行重
  • error while loading shared libraries: ../../lib/libopencv_core.so

    error while loading shared libraries lib libopencv core so 原文 http blog chinaunix net uid 27134408 id 5122776 html 最近做Op
  • SonarQube - org.sonar.process.MessageException: Unsupported JDBC driver provider: mysql

    使用docker安装最新的SonarQube 启动SonarQube报错 Exception in thread main org sonar process MessageException Unsupported JDBC driver
  • [shell编程]、()、(())、[]、[[]]的区别

    默认的变量类型是字符串 所以 str1 str2 就是一串字符串 我们想要判断它们是否相等必须使用中括号 str1 str2 1 中括号 表示条件测试 注意这里的空格很重要 要注意在 后面和 前面都必须要有空格 常用判断 d FILE 如果
  • 企业为什么要融资和上市

    这里面涉及到两个概念 即融资和上市 让我们先来理理这两者之间的逻辑辩证关系 其实根据我们的观察和调研发现 目前市场上许多人对上市这件事有着十分魔性的认知 小A觉得上市前融资轮次越多越好 小B认为上市后就是为了圈钱 小C觉得IPO的速度越快越
  • ISP之DPC(坏点校正)模块

    DPC Defective Photosites Correction即坏点校正 一 DPC的意义 图像传感器上由于自身工艺技术造成的瑕疵 如光线采集的点存在缺陷 导致在光电转换过程中某些像素值不准确 我们称之为坏点 Defect Pixe
  • 星环科技线上技术分享课“星课堂”开播,快来一探究竟

    星课堂 深度解读系列上线啦 4 9月 10期线上课带你深度了解星环科技2021全系列新品细节 关于星环科技 星环科技致力于打造 云计算 大数据 数据库 人工智能 的基础平台产品 领航基础软件新纪元 经过多年自主研发 星环科技建立了多个产品系
  • Mysql事务隔离机制

    SQL隔离机制 所谓隔离机制 指的是读与写之间的隔离 指的是在多事务并行的时候 A事务的读与B事务的写之间的隔离 也就是说B事务的写对A事务的可见性 多事务并发运行的时候 同时读写一个数据 可能会出现脏写 脏读 不可重复读 幻读几个问题 脏