事物的隔离性和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)

大家都在看

  • js中创建正则对象时,变量中存在转义字符(’/’,’.’等)时,是否需要转义?

    使用直接量创建正则时,很方便,但是如果存在变量时,不适用。 使用正则对象(RegExp)创建时,对于变量中的转义字符不需要处理。 另外测试正则地址: https://develop…

    数据库 2023年6月11日
    098
  • Harbor部署

    harbor 无论是使用Docker-distribution去自建仓库,还是通过官方镜像跑容器的方式去自建仓库,通过前面的演示我们可以发现其是非常的简陋的,还不如直接使用官方的D…

    数据库 2023年6月14日
    079
  • 第一篇博客

    这是我在博客园的第一篇博客,用来纪念以下,同时也是写博客的试水标记 Original: https://www.cnblogs.com/zht1702/p/15081310.htm…

    数据库 2023年6月14日
    059
  • MYSQL–>索引

    概述 索引是帮助MYSQL 高效获取数据的 有序数据结构 数据库维护着满足特定查找算法的数据结构,这种数据结构以某种方式指向数据。 这样就可以在数据结构上实现高级查找方法,这种数据…

    数据库 2023年6月14日
    077
  • 聊斋-河间生

    人的善恶在转瞬之间就可以改变,发现错误时往往已经差之千里了,但是发现错误及时改正这不也是很美好的一件事情么?河间生就是讲了这么一件事情。 主角简介:河间某生,家里比较富裕,烧火用的…

    数据库 2023年6月6日
    090
  • Matery主题自定义(一)黑夜模式

    黑夜模式 作为一个前端学习者,自然懂得黑夜模式的重要性,可惜主题原生未提供,那就自己弄吧 参考其他优秀产品的黑夜模式,得出共性: 那就是黑夜模式的背景一般不会是纯黑(#000);而…

    数据库 2023年6月16日
    065
  • 记录下在阿里云linux上安装与配置Mysql

    环境:阿里云ECS服务器,系统为centos7.2 用户:root 参考博客: https://blog.csdn.net/kunzai6/article/details/8193…

    数据库 2023年6月16日
    0104
  • 正在运行转换: System.Runtime.Remoting.RemotingException: 无法加载类型“EnvDTE._DTE

    在编写T4,引用envdte时,遇到如下错误,解决方案:右击引用中的envdte,属性中将”嵌入互操作类型”为false,重新编译库即可。 错误信息如下: …

    数据库 2023年6月14日
    084
  • Try-with-resources are not supported at language level ‘5’

    Try-with-resources are not supported at language level ‘5’没有指定maven版本导致 的 指定ma…

    数据库 2023年6月16日
    060
  • css height属性中的calc方法

    例如父盒子是100%的高度 盒子里面的head部分固定位140px 内容部分始终为剩余的全部高度 height: calc(100% – 140px); “…

    数据库 2023年6月16日
    0124
  • 第17章 触发器

    第17章 触发器 在实际开发中,我们经常会遇到这样的情况:有 2 个或者多个相互关联的表,如 商品信&#x…

    数据库 2023年6月6日
    0113
  • Gorm 的黑魔法

    开发过程中,看到同事的代码写了这么一段: db = db.Session(&gorm.Session{Context: db.Statement.Context}).Fir…

    数据库 2023年6月9日
    090
  • DDD(Domain Driver Design)领域驱动模型

    Domain Primitive(DP) DP概念DP 是 DDD 中的一个基础概念,是 DDD 中可以执行的一个最小单元,最直接的体现是,将业务相关的参数定义在一个特定的领域中(…

    数据库 2023年6月6日
    0109
  • 2_JDBC

    使用客户端工具访问数据库, 需要手工建立连接, 输入用户名和密码登陆, 编写SQL语句, 点击执行, 查看操作结果(结果集或受行数影响) 在实际开发中, 当用户的数据发生改变时, …

    数据库 2023年6月11日
    055
  • COM组件 学习笔记

    COM组件是 以Win32动态链接库dll或可执行文件exe的形式发布的可执行代码组成的; COM组件是动态链接的,COM使用dll将组件动态链接起来; COM组件是语言无关的; …

    数据库 2023年6月14日
    062
  • 微服务架构设计模式

    内容简介 成功地开发基于微服务架构的应用软件,需要掌握一系列全新的架构思想和实践。在这本书籍中解释了 44 个架构设计模式,这些模式用来解决诸如服务拆分、事务管理、查询和跨服务通信…

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