浅谈mysql mvcc

目录

前言

mvcc 是如何工作的?

数据的更新


前言

mvcc 与一个事物的隔离级别有关,未提交读永远读的是当前值,串行化是通过加锁实现,这两种隔离级别都与mvcc 没有任何关系。只要一提到mvcc应该想到的是读提交以及可重复读,大家有没有想过都是mvcc,为啥这两个隔离级别所呈现的结果有些不一样呢?难道会有两套mvcc 吗?当然不是,对于这个问题,稍后我会说明的。

我先举一个简单的例子。下面是一个表的初始化语句。

CREATE TABLE `t` (
  `id` int(11) NOT NULL,
  `k` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;
insert into t(id, k) values(1,1),(2,2);
sessionAsessionBsessionA

在此我说明下,sessionA 是在同一个事物下,事务的隔离级别是可重复读,sessionB 是另外一个事物。是不是感觉很神奇,sessionB 对数据操作成功了,sessionA 没有收到任何干扰。

是不是感觉sessionA 在begin 的时候像相机一样为数据表拍了一张快照。而这个快照也是我们常说的一致性读视图即 consistent read view。它的作用是事务执行期间用来定义“我能看到什么数据”。

mvcc 是如何工作的?

在上面我们讲到了快照,大家是不是感觉我在扯淡,100G的库,你也去快照,你要拷贝100G的数据,别人不会拍死你,放心好了拍不死我的。

其实在启动一个事物的时候,并不需要拷贝数据,只需要在事物系统申请一个事物id 叫做 transaction id,这个id 是原子递增的,意味着一个数据库不会出现两个相同的事物id

每行数据也都是有多个版本的。每次事务更新数据的时候,都会生成一个新的数据版本,并且把 transaction id 赋值给这个数据版本的事务 ID,记为 row trx_id。同时,旧的数据版本要保留在undo log 里,并且在新的数据版本中,能够有信息可以直接拿到它。

可以这么说,数据表中的一行记录,其实可能有多个版本,每个版本都有自己的row trx_id。

按照可重复读的定义,一个事物启动的时候,能够看到所有已经提交的事物结果。但是之后其他事物的更新,它却看不见。

它是怎么找到自己能够看见的数据呢,会拿到每个版本的 row trx_id,如果是在我启动以后生成的row trx_id,继续往前找,直到找到自己提交的或者是本事物启动之前提交的。

为了方便比较,在实现上,innodb 为每个事物构建一个数组,用来保存这个事物启动瞬间,当前正在“活跃” 的所有事物ID。“活跃” 指的是,启动了还没有提交的。

数组里面事务 ID 的最小值记为低水位,当前系统里面已经创建过的事务 ID 的最大值加 1 记为高水位。

这个视图数组和高水位,就组成了当前事物的一致性视图。

而数据版本的可见性规则,就是基于数据的 row trx_id 和这个一致性视图的对比结果得到的。

就拿一致性视图而言,规则是这样的:

  1. 如果 row trx_id 小于这个视图数组的最小值,说明已经提交了,那么这个数据就是可见的。

  2. 如果 row trx_id 大于这个高水位,肯定不可见呀,说明事物还没有创建

  3. 如果 row trx_id 在 最小值和高水位之间又有两种情况:row trx_id刚好就在视图数组是说明还没有提交也不可见,不在视图数组里说明提交了就可见。

所以你现在知道了,InnoDB 利用了“所有数据都有多个版本”的这个特性,实现了“秒级创建快照”的能力。

所以一个数据版本,对于一个事务视图来说,除了自己更新总是可见以外,有三种情况:

  1. 版本未提交,不可见;

  2. 版本已提交,但是是在视图创建后提交的,不可见;

  3. 版本已提交,而且是在视图创建前提交的,可见。

下面我在在回到最开始提到的那个问题,读提交为啥又有些不一样呢,让我们在回顾一下什么是读提交,在事务中,我们可以读到已经提交的事物,只要在我事物中的任何一个时刻提交的,我都可以读到。上面的规则对于读提交同样适用,只不过读提交是在每个select语句都会去申请一个transaction id作为它的row trx_id,同时也会构建一个新的事物数组。

数据的更新

上面我们讲到了mvcc,其实只是在select 用到,如果是update ,或者下面的语句。

select k from t where id=1 lock in share mode;
​
select k from t where id=1 for update;

大家都知道更新数据都是先读后写的,而这个读,只能读当前的值,称为“当前读”(current read)。

或者是select 语句加上了 share mode 共享锁 或者 for update 拍他锁,这些都只能用到当前读,与mvcc 没有一点关系了。

所以这些语句执行后,会对行进行加锁,update 加行锁,share mode 加的是读锁, for update 加的是写锁。读到最新的数据

而这些锁都是两阶段锁,从加锁开始到事物结束。这么做对于数据库来说也是无赖之举,为了保证数据的一致性,是数据的同步技术。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Node.js中的缓存策略和缓存技巧

在Node.js中,缓存策略和缓存技巧是提升应用性能和用户体验的关键因素。通过有效地利用缓存,我们可以显著减少系统资源的消耗,加快数据访问速度,从而提升整体的网站性能。本文将针对Node.js中的缓存策略和缓存技巧展开深入探讨&…

php PhpSpreadsheet 读取日期变数字问题解决

问题描述: 使用PhpSpreadsheet 读取表格数据,日期格式读取后变成数字,如下图: 解决方案: $cell $sheet->getCell(H . $row)->getValue(); $toTimestamp \PhpOffice\PhpSpreadsheet\Shared\Date::excelToTimes…

CentOS安装GUI图形界面

CentOS安装图形界面 CentOS minimal环境安装图形界面。 列出所有可用的Environment Groups yum group list yum groupinfo "GNOME Desktop"选择GNOME Desktop软件包组进行安装 yum groupinstall -y GNOME Desktop1 如果要通过GUI配置网络需要安装Server with GU…

深入理解Java泛型及其在实际编程中的应用

第1章:泛型的起源与重要性 大家好,我是小黑,在Java里,泛型(Generics)是一种不可或缺的特性,它允许咱们在编码时使用类型(Type)作为参数。这听起来可能有点绕&#xff0c…

倒模专用制作耳机壳UV树脂:改性丙烯酸树脂

倒模专用制作耳机壳的UV树脂是经过改性的丙烯酸树脂,具有高透明度、高粘度、快速固化的特点。这种树脂可以通过紫外线光固化,快速形成坚硬的表面,并且具有较高的硬度和耐磨性,因此非常适合用于制作耳机壳。 此外,改性丙…

anaconda简介以及安装(Windows)

介绍 Anaconda是一个开源的Python发行版本,它是一个打包的集合,里面预装了conda、Python、众多packages、科学计算工具等。Anaconda的目的是方便使用Python进行数据科学研究,它涵盖了数据科学领域常见的Python库,并且自带了专门用…

SpringBoot 整合WebService

文章目录 WebService1.简单介绍WebService1.1. 类型1.2. 架构1.3. 主要特点1.4. 使用场景1.5. Web服务标准和技术 2.案例-WebServiceDemo2.1.引入配置文件2.2.创建接口2.3.创建接口实现类2.4.创建WebService配置类2.5.测试 WebService Web服务(Web Services&#xf…

【C语言】指针初阶2.0版本

这篇博文我们来继续学习指针的其他内容 指针2.0 传值调用与传址调用传值调用传址调用 一维数组与指针理解数组名使用指针深入理解一维数组 二级指针指针数组二维数组与指针 传值调用与传址调用 在开始之前,我们需要先了解这个概念,后面才能够正常的学习…

android移动应用开发基础答案,安卓工程师面试题

一线企业的app都是多线程和多进程的,而Android进程间通信机制就是Binder,原生的线程间通信则是Handler,Binder和Handler是了解安卓运行机制必须要掌握的一个知识点,更是一线企业面试必问的知识点! 以下几道就是大厂关于…

Ansible的playbook的编写和解析

目录 什么是playbook Ansible 的脚本 --- playbook 剧本 实例部署(使用playbook安装启动httpd服务) 1.编写一个.yaml文件 在主机下载安装http,将配置文件复制到opt目录下 运行playbook 在192.168.17.77主机上查看httpd服务是否成功开启…

Codeforces Round 930 (Div. 2)题解

A. Shuffle Party(Problem - A - Codeforces) 题目大意:给定一个n长数组,并使得a[i]i,现在定义一种操作swap(k):找出k的最大不等于自己的除数d,交换a[k]和a[d],k从1开始直到n结束,问…

训练1 : 老头

以前用blender做的特效 总结 头发很费时间, 需要参考和练习眼窝周边结构还有些待准确把握从光与影中揣摩轮廓形状 从少量面掌握大体, 从多数面雕刻细节

云时代【5】—— LXC 与 容器

云时代【5】—— LXC 与 容器 三、LXC(一)基本介绍(二)相关 Linux 指令实战:使用 LXC 操作容器 四、Docker(一)删除、安装、配置(二)镜像仓库1. 分类2. 相关指令&#xf…

教师招聘和事业编d类有什么区别吗

每年都有大批怀揣教育梦想的年轻人,站在职业的十字路口,对未来充满期许与疑惑。他们中的许多人都会面临这样一个问题:教师招聘和事业编D类,到底有什么区别?今天,就让我来为你揭开这两者的神秘面纱。 别被这…

基于session注册JAva篇springboot

springboot3全家桶,数据库 :redis,mysql 背景环境:邮箱验证码,验证注册 流程:先通过邮箱验证,发送验证码,将获取到的session和验证码,存入redis里(发送邮箱…

3d模型版本转换器注意事项---模大狮模型网

在使用3D模型版本转换器时,有一些注意事项可以帮助您顺利完成模型转换并避免不必要的问题: 数据完整性:在进行模型转换之前,确保您的原始3D模型文件没有损坏或缺失数据。损坏的文件可能导致转换器无法正常处理或输出错误的结果。 …

【前端素材】推荐优质在线大气数码商城电商网页ClassiList平台模板(附源码)

一、需求分析 1、系统定义 电子数码电商平台是专门销售电子数码产品(如手机、电脑、相机、智能设备等)的在线电子商务平台。这些平台提供了一个便捷的购物环境,让消费者可以方便地浏览、比较和购买各种电子数码产品。 2、功能需求 在线大…

常见外设学习以及无线通信频率

常见外设 UART UART(Universal Asynchronous Receiver/Transmitter,通用异步收发器)是一种异步、串行、全双工的通信总线。 UART 有3根线,分别是:发送线(TX)、接收线(RX&#xff…

找不到msvcp140.dll无法运行程序如何处理?分享5种解决方法

在计算机系统运行过程中,如果无法找到必要的动态链接库文件msvcp140.dll,可能会引发一系列的问题与故障。这个特定的dll文件是Microsoft Visual C Redistributable Package的一部分,对于许多基于此编译环境开发的应用程序至关重要。缺失msvcp…

Android WebView访问网页+自动播放视频+自动全屏+切换横屏

一、引言 近期,我发现电视家、火星直播等在线看电视直播的软件都已倒闭,而我奶奶也再无法通过这些平台看电视了。她已六十多岁,快七十岁啦。这些平台的倒下对我来说其实没有多大的影响,但是对于文化不多的她而言,生活中…