当前位置: 首页 > news >正文

MySQL MVCC

总结自小林coding,bojiangzhou

脏读、不可重复读、幻读 说的都是并发读取的问题,最简单的方式就是给记录加一把锁,不管是更新、读取记录都需要竞争到这把锁之后才能操作。但这种方式的并发性能可想而知会有多么低。

于是 InnoDB 就设计了MVCC来解决并发读取的问题,MVCC 就是多版本并发控制(Multi-Version Concurrency Control)。在 RCRR 这两种隔离级别下执行SELECT查询时,通过访问记录的版本链,而不需要加锁,这样使得不同事务的读-写操作可以并发执行,从而提升数据库的性能。

MVCC需要依赖undo log版本链:

  • 对于使用 RU 隔离级别的事务来说,由于可以读到未提交事务修改过的记录,所以直接读取记录的最新版本就好了。

  • 对于使用 RCRR 隔离级别的事务来说,都必须保证读到已提交事务修改过的记录,如果另一个事务修改的记录还未提交,是不能直接读取记录的最新版本的,此时就可以沿着undo版本链查找当前事务可见的版本。

ReadView

那如何判断版本链上的哪个版本是当前事务可见的呢?

InnoDB 设计了一个 ReadView,在执行一个事务的时候就会创建一个ReadView。ReadView 有四个关键属性:

  • m_ids :指的是在创建 Read View 时,当前数据库中「活跃事务」的事务 id 列表,注意是一个列表,“活跃事务”指的就是,启动了但还没提交的事务。

  • min_trx_id :指的是在创建 Read View 时,当前数据库中「活跃事务」中事务 id 最小的事务,也就是 m_ids 的最小值。

  • max_trx_id :这个并不是 m_ids 的最大值,而是创建 Read View 时当前数据库中应该给下一个事务的 id 值,也就是全局事务ID(Max Trx Id);

  • creator_trx_id :指的是创建该 Read View 的事务的事务 id。事务中只有在执行了增删改操作时才会分配一个事务ID,如果是一个只读事务,那 creator_trx_id 默认就为0

MVCC 流程

undo log 中的隐藏列 trx_id 表示产生这条 undo log 时的事务的事务ID。判断此版本是否可访问的依据就是用 undo log 中的 trx_id 属性值与 ReadView 中的各个属性做比较。

通过如下步骤来判断版本是否可被访问:

  • ① 如果 trx_id 等于 creator_trx_id ,说明当前事务在访问它自己修改过的记录,所以该版本记录可以被当前事务访问。(可以自己访问自己的事务)

  • ② 如果 trx_id 小于 min_trx_id,说明生成该版本记录的事务在当前事务生成 ReadView 前已经提交,所以该版本记录可以被当前事务访问。(可以访问已经提交的事务)

  • ③ 如果 trx_id 大于或等于max_trx_id,说明生成该版本记录的事务在当前事务生成 ReadView 后才开启,所以该版本记录不可以被当前事务访问。(不能访问“未来”的事务)

  • ④ 如果 trx_idmin_trx_idmax_trx_id 之间,此时再判断一下 trx_id 是不是在 m_ids 列表中,如果在,说明创建 ReadView 时生成该版本记录的事务还是活跃的,该版本记录不可以被访问(不能访问同期未提交的事务);如果不在,说明创建 ReadView 时生成该版本记录的事务已经被提交,该版本记录可以被访问。(可以访问同期已提交的事务)

RC 和 RR

READ COMMITTEDREPEATABLE READ 隔离级别的区别就是它们生成ReadView的时机不同。

  • READ COMMITTED 是每次查询前都会生成一个独立的 ReadView。

  • REPEATABLE READ 则只在第一次查询前生成一个 ReadView,之后的查询都重复使用这个 ReadView。

  • READ UNCOMMITTED 则不需要生成 ReadView,直接读取行记录的数据。

快照读和当前读

简单的SELECT查询,是读取undo版本链上的一个快照版本,可以称为快照读一致性非锁定读。由于是读取的快照,因此在RR隔离级别下可以避免幻读的发生。

但如果是INSERT、DELETE、UPDATE语句,例如下面的SQL,这个 UPDATE 语句会更新 balance=0 的记录,这种方式就称为当前读,读取的是最新的数据。当前读能读取到别的事务已提交的修改,就可能会产生幻读的问题。UPDATE account SET balance=100 WHERE balance = 0;

而对于幻读现象,不建议将隔离级别升级为串行化,因为这会导致数据库并发时性能很差。MySQL InnoDB 引擎的默认隔离级别虽然是「可重复读」,但是它很大程度上避免幻读现象,解决的方案有两种:

  • 针对快照读(普通 select 语句),是通过 MVCC 方式解决了幻读,因为可重复读隔离级别下,事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,即使中途有其他事务插入了一条数据,是查询不出来这条数据的,所以就很好了避免幻读问题。

  • 针对当前读(select ... for update 等语句),是通过 next-key lock(记录锁+间隙锁)方式解决了幻读,因为当执行 select ... for update 语句的时候,会加上 next-key lock,如果有其他事务在 next-key lock 锁范围内插入了一条记录,那么这个插入语句就会被阻塞,无法成功插入,所以就很好了避免幻读问题。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • HybridCLR原理中的重点总结
  • WordPress的性能优化有哪些方法?
  • VIM三种模式的操作
  • PyTorch复现PointNet——模型训练+可视化测试显示
  • 【机器学习】机器学习详解-小白入门(随记)
  • Web学习day02
  • ONLYOFFICE8.1版本桌面编辑器——功能测评
  • 设计模式——单例模式
  • VB 函数
  • (2024)docker-compose实战 (9)部署多项目环境(LAMP+react+vue+redis+mysql+nginx)
  • 【C++精华铺】11.STL vector模拟实现
  • helm安装解决无授权问题
  • 宝塔:如何开启面板ssl并更新过期ssl
  • 【ROS2】中级:Launch-管理大型项目
  • Flutter RSA公钥转PEM
  • @angular/forms 源码解析之双向绑定
  • emacs初体验
  • Java基本数据类型之Number
  • java中的hashCode
  • java中具有继承关系的类及其对象初始化顺序
  • mockjs让前端开发独立于后端
  • Vue 动态创建 component
  • WePY 在小程序性能调优上做出的探究
  • yii2中session跨域名的问题
  • 初识 webpack
  • 第十八天-企业应用架构模式-基本模式
  • 动态魔术使用DBMS_SQL
  • 基于HAProxy的高性能缓存服务器nuster
  • 入门级的git使用指北
  • 使用API自动生成工具优化前端工作流
  • 通过几道题目学习二叉搜索树
  • 用jQuery怎么做到前后端分离
  • 正则与JS中的正则
  • 智能网联汽车信息安全
  • media数据库操作,可以进行增删改查,实现回收站,隐私照片功能 SharedPreferences存储地址:
  • ​如何使用ArcGIS Pro制作渐变河流效果
  • #Linux杂记--将Python3的源码编译为.so文件方法与Linux环境下的交叉编译方法
  • (11)MSP430F5529 定时器B
  • (4)事件处理——(6)给.ready()回调函数传递一个参数(Passing an argument to the .ready() callback)...
  • (AtCoder Beginner Contest 340) -- F - S = 1 -- 题解
  • (void) (_x == _y)的作用
  • (八十八)VFL语言初步 - 实现布局
  • (二刷)代码随想录第16天|104.二叉树的最大深度 559.n叉树的最大深度● 111.二叉树的最小深度● 222.完全二叉树的节点个数
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • (一)eclipse Dynamic web project 工程目录以及文件路径问题
  • (原創) 未来三学期想要修的课 (日記)
  • (转)Android学习系列(31)--App自动化之使用Ant编译项目多渠道打包
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • ******之网络***——物理***
  • .bashrc在哪里,alias妙用
  • .net core MVC 通过 Filters 过滤器拦截请求及响应内容
  • .NET Micro Framework初体验(二)
  • .NET 中的轻量级线程安全
  • .NetCore发布到IIS