事物的隔离性和MVCC

事物的隔离性

mysql的服务端是支持多个客户端同时与之连接的,每个客户端可能还并发了好几个连接,所以mysql是需要同时处理很多事情的,每一件独立的事情就叫做事务。我们知道事务有一个叫隔离性的特性,隔离性理论上是指在某个事物对某个数据进行访问时,其他的事务就应该排队知道访问数据的事务提交才能继续访问该数据。但是这样对性能的影响就太大了,但是我们又必须保持一定的隔离性,所以就需要折中一下。

事务并发可能的问题

首先,让我们来看看如果不能保证绝对孤立会遇到什么问题。

[En]

First, let’s take a look at what problems will be encountered if there is no guarantee of absolute isolation.

  • 脏写

如果一个事务修改了由另一个未提交的事务修改的数据,这意味着发生了脏写入。

[En]

If one transaction modifies data modified by another uncommitted transaction, this means that a dirty write has occurred.

  • 脏读

如果一个事务读取由另一个未提交的事务修改的数据,这意味着发生了脏读取。

[En]

If one transaction reads data modified by another uncommitted transaction, this means that a dirty read has occurred.

  • 不可重复读

如果提交另一个事务后的最新值可以在同一事务中读取,则另一个事务对该数据所做的每一次更改都将导致该事务读取不同的最新值,这意味着发生了不可重复的读取。

[En]

If the latest value after the commit of another transaction can be read in the same transaction, each change made by another transaction to this data will cause the transaction to read a different latest value, which means that an unrepeatable read has occurred.

  • 幻读

如果一个事务根据一些记录找到一些记录,然后另一个事务将满足这些条件的记录插入到表中,当该事务再次使用该条件查询时,它会找出上次没有找到的数据,即另一个事务刚刚插入的数据,这称为虚读。

[En]

If one transaction finds some records based on some, and then another transaction inserts records that meet these conditions into the table, when the transaction queries with that condition again, it will find out the data that was not found last time, that is, the data just inserted by another transaction, which is called illusory reading.

小贴士:

不可重复读和幻读确实有点相似,但不可重复读重点在于update和delete,而幻读的重点在于insert。对于前者,要避免只需锁住满足条件的已有记录即可,避免后者就需要锁住满足条件的记录(包括存在的和不存在的),不存在的记录如何才能锁住呢?所以锁的范围需要扩大到满足条件的相邻范围的记录(临键锁)

事务的隔离级别

这时就出现了一个标准用来定义上面说的折中的程度,在SQL标准中定义了4个隔离级别:

  • READ UNCOMMITTED:读未提交
  • READ COMMITTED:读已提交
  • REPEATABLE READ:可重复读
  • SERIALIZABLE:可串行化

SQL标准中规定,针对不同的隔离级别并发事务可以发生不同严重程度的问题

事物的隔离性和MVCC

MVCC

MVCC解决了事务并发时读和写同时进行互不影响的问题,从而提升系统性能。mvcc并不能解决完全解决脏读和不可重复读的问题,如果innoDB只有mvcc没有锁,那么当前事务确实没办法读取到未提交的数据,但是可以修改。

对于已提交事务和可重复事务,都必须确保读取的记录是由已提交事务修改的记录,因此,如果要确保读取和写入不相互影响,核心问题是确定在读取记录时版本链中的哪个版本对当前事务可见。

[En]

For both committed and repeatable transactions, it is necessary to ensure that the records read are those modified by committed transactions, so if you want to ensure that reads and writes do not affect each other, the core problem is to determine which version in the version chain is visible to the current transaction when reading the record.

MVCC原理

对于innoDB存储引擎来说,每张表中都含有两个必要的隐藏列trx_id和roll_pointer。每次对某条记录进行改动时,都会把旧的版本写入到 undo日志中,然后在这个roll_pointer列中存储旧版本在undo日志的地址,可以通过它来找到该记录修改前的信息,同时将进行改动的事务id写入trx_id列。

事物的隔离性和MVCC

在可重复读的隔离模式下每个事务都会生成一个 ReadView ,主要包含4个重要的内容:

m_ids :表示在生成 ReadView 时当前系统中活跃的读写事务的 事务id 列表。

min_trx_id :表示在生成 ReadView 时当前系统中活跃的读写事务中最小的 事务id ,也就是

m_ids 中的最 小值。

max_trx_id :表示生成 ReadView 时系统中应该分配给下一个事务的 id 值。

creator_trx_id :表示生成该 ReadView 的事务的 事务id 。

有了这个 ReadView ,这样在访问某条记录时,只需要按照下边的步骤判断记录的某个版本是否可见:

如果被访问版本的 trx_id 属性值与 ReadView 中的 creator_trx_id 值相同,意味着当前事务在访问它自己 修改过的记录,所以该版本可以被当前事务访问。

如果被访问版本的 trx_id 属性值小于 ReadView 中的 min_trx_id 值,表明生成该版本的事务在当前事务生 成 ReadView 前已经提交,所以该版本可以被当前事务访问。

如果被访问版本的 trx_id 属性值大于 ReadView 中的 max_trx_id 值,表明生成该版本的事务在当前事务生 成 ReadView 后才开启,所以该版本不可以被当前事务访问。

如果被访问版本的 trx_id 属性值在 ReadView 的 min_trx_id 和 max_trx_id 之间,那就需要判断一下 trx_id 属性值是不是在 m_ids 列表中,如果在,说明创建 ReadView 时生成该版本的事务还是活跃的,该版本不可以被访问;如果不在,说明创建 ReadView 时生成该版本的事务已经被提交,该版本可以被访问。

如果数据的一个版本对当前事务不可见,则按照版本链查找数据的下一个版本,继续执行上述步骤以确定可见性,依此类推,直到版本链中的最后一个版本。如果最后一个版本不可见,则表示该记录对交易完全不可见,查询结果中不包含该记录。

[En]

If one version of the data is not visible to the current transaction, follow the version chain to find the next version of the data, continue to follow the above steps to determine visibility, and so on, until the last version in the version chain. If the last version is not visible, it means that the record is completely invisible to the transaction, and the query result does not include the record.

上面两段引用来自于《MySQL是怎样运行的:从根儿上理解MySQL》,我觉得已经很明白了。

我写文章试图纠正,但水平有限,欢迎老板斧头纠正。

[En]

I write articles to try to be correct, but the level is limited, welcome boss axe correct.

相关资源:

MySQL是怎样运行的:从根儿上理解MySQL

Original: https://www.cnblogs.com/hjsh/p/16632370.html
Author: 时有限学无涯
Title: 事物的隔离性和MVCC

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/504922/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 你真的懂Python命名吗?

    转载请注明出处❤️ 作者:测试蔡坨坨 原文链接:caituotuo.top/7417a7f0.html 大家好,我是测试蔡坨坨。 今天,我们来聊一下Python命名那些事儿。 名为…

    数据库 2023年6月11日
    0148
  • CentOS 安装 Docker CE

    CentOS 安装 Docker CE 警告:切勿在没有配置 Docker YUM 源的情况下直接使用 yum 命令安装 Docker. 准备工作 系统要求 Docker CE 支…

    数据库 2023年6月6日
    085
  • innoDB对MVCC的实现

    InnoDB存储引擎在 RR 级别下通过 MVCC和 Next-key Lock 来解决幻读问题: 1、执行普通 select,此时会以 MVCC 快照读的方式读取数据 在快照读的…

    数据库 2023年6月16日
    092
  • MySQL 学习笔记(六)—character 与 collation

    A character set is a set of symbols and encodings. A collation is a set of rules for compa…

    数据库 2023年6月16日
    0117
  • MySQL实战45讲 9

    09 | 普通索引和唯一索引,应该怎么选择? 每个人都有一个唯一的身份证号,而且业务代码已经保证了不会写入两个重复的身份证号。如果市民系统需要按照身份证号查姓名,就会执行类似这样的…

    数据库 2023年6月16日
    0110
  • 第15章 存储过程与函数

    MySQL从5.0版本开始支持存储过程和函数。存储过程和函数能够将复杂的SQL逻辑封装在一起,应用程序无须关注存储过程和函数内部复杂的SQL逻辑,而只需要简单地调用存储过程和函数即…

    数据库 2023年6月6日
    093
  • MySQL实战45讲 17

    17 | 如何正确地显示随机消息? 场景:从一个单词表中随机选出三个单词。 表的建表语句和初始数据的命令如下,在这个表里面插入了 10000 行记录: CREATE TABLE w…

    数据库 2023年6月14日
    065
  • 数据库的常用命令

    1. 数据操作类语句: SELECT:从数据库表&#x4E2D…

    数据库 2023年5月24日
    0105
  • MDC日志链路设计

    正文 本篇博客主题是MDC(MDC 全称是 Mapped Diagnostic Context,可以粗略的理解成是一个线程安全的存放诊断日志的容器),其具体流程是通过某些标识将整个…

    数据库 2023年6月6日
    0100
  • 链表问题一些常用的套路与方法

    概述 链表问题应该是数据结构中比较基础的一类问题,但同时也是在面试中常考的一类问题。但是围绕链表问题的一些基本方法或者处理思想,也无外乎那几类,因此本文尝试对链表常用的一些方法或者…

    数据库 2023年6月11日
    080
  • python tkiner实现自动打包程序

    环境 python3.x 使用前请确保安装pyinstaller库 本程序还未完善,可以自行完善 若要使用加密,请自行安装cryptodome库 python;gutter:tru…

    数据库 2023年6月11日
    088
  • web开发模式

    前后端不分离 返回的是html的内容,需要在服务端拿到数据库的数据,再渲染给模板层,最后将渲染好的模板返回给浏览器! 前后端分离 前后端分离:只需要在浏览器上运行JS代码,使用aj…

    数据库 2023年6月14日
    095
  • DB审核查询平台Archery–安装部署可能遇到的问题

    Archery是archer的分支项目,定位于SQL审核查询平台,旨在提升DBA的工作效率,支持多数据库的SQL上线和查询,同时支持丰富的MySQL运维功能,所有功能都兼容手机端操…

    数据库 2023年6月16日
    083
  • Host-Only模式下虚拟机无法联网问题

    环境: 镜像:Linux CentOS7——————————…

    数据库 2023年6月11日
    093
  • 调试Archery连接SQL Server提示驱动错误

    当我们在调试Archery的时候,连接SQL Server 会报错,而MySQL部分没有问题。报错信息如下: Error: (‘01000’, "[01000] [uni…

    数据库 2023年6月16日
    0140
  • Java并发编程之AQS以及源码解析

    文章目录 概览 实现思路 实现原理 * 源自CLH锁 AQS数据模型 CAS操作 主要方法 * 自定义同步器的实现方法 AQS定义的模板方法 源码解读 * 等待状态释义 AQS获取…

    数据库 2023年6月6日
    077
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球