二种MVCC对比分析

文章目录

  • 前言
  • MVCC
  • Innodb的MVCC
    • 版本链
    • 回滚与提交
    • 可见性判断
  • Oracle的MVCC
    • 版本链
  • PostgreSQL的MVCC
    • MVCC实现
    • 可见性判断
    • 特点

前言

​    MVCC(多版本并发控制,Multi-Version Concurrency Control)是一种数据库管理系统(DBMS)中用于处理并发访问的机制。它的核心思想是通过保存数据的多个版本来实现高效的读写并发操作,避免事务之间的阻塞,从而提高系统性能, 这篇文章将从几个数据库来分析

MVCC

MVCC是为了在数据库中, 读写不阻塞的情况下, 提供一致性读的功能

​​    在并发操作中,当正在写时,如果有用户在读,这时写可能只写了一半,如一行的前半部分刚写入,后半部分还没有写入,这时读取到的数据行,可能是前半部分是新数据,后半部分是旧数据的不一致的行。解决这个问题的最简单的办法是 使用读写锁,写的时候,不允许读,正在读的时候也不允许写,但这种方法导致读和写不能并发。于是,有人就想到了一种能够让读写并发的方法,这种方法就 是MVCC, MVCC的方法是写数据时,旧的版本数据并不删除,并发的读还能读到旧的版本数据,这样就不会有问题了

​    从几个经典的数据库来看MVCC可以分为两种, 一种是基于版本链的MVCC, 比如MySQL的Innodb存储引擎, 还有Oracle数据库, 这种是将旧数据放在回滚段, 通过一条记录的回滚指针来找到上一个版本, 另一种是直接将旧版本的数据依然放在当前数据文件中, 比如PostgreSQL

Innodb的MVCC

​ ​    对于一条记录, 除开我们在创建表时规定的列, 还有几个隐藏字段, 在MVCC我们需要关注这俩个

在这里插入图片描述

  • trx_id : 创建这条记录的事务号
  • roll_pointer : 回滚指针, 指向上一个版本

版本链

通过回滚指针就可以形成版本链

在这里插入图片描述

  • 在Innodb中存在purge线程,它会查询那些比现在最老的活动事务还早的undo log,并删除它们,从而保证undo log文件不至于无限增长。

回滚与提交

  • 正常提交 : 一当事务正常提交时, innodb只需要更改事务状态为commit即可,不需做其他额外的工作
  • 回滚 : Rollback需要根据当前回滚指针从undo log中找出事务修改前的版本,并恢复。如果事务影响的行非常多,回滚则可能会很慢并且还会加行锁, 阻塞其他事务,回滚时,也会产生redo日志
  • Innodb的commit效率高,Rollback代价大

可见性判断

​ Innodb判断一条记录对于一个事务是否可见是通过读视图 ( Read View )来实现的

读视图可以看作一个数据结构, 里面有几个重点字段

  • Create_trx_id : 表示创建该读视图的事务id
  • m_ids : 表示创建该读视图时, MySQL中活跃的事务id集合
  • min_try_id : 表示创建该读视图时, MySQL中活跃的事务id最小值
  • max_try_id : 表示创建该读视图时, MySQL中全局最大事务id+1

那么对于一条记录

  • 如果修改这条记录的事务id比读视图中的min_id还小, 表示这条记录是在创建该读视图之前就修改的, 那么对于当前事务这条数据是可见
  • 如果这个id比读视图的Max_id还大, 说明是创建该读视图之后才修改的, 那么对于当前事务就是不可见的
  • 如果在两者之间, 再看读视图中的m_ids, 如果这个id存在读视图的m_ids里, 说明这条记录还没被提交, 那么对于当前事务不可见, 如果不在, 说明该记录的事务已经被提交, 那么对于当前事务来说就可见

​    在Innodb的事务隔离级别中, 读提交和可重复读的区别就是创建读视图的时机不同, 读提交是在该事务每次执行语句都会创建一个读视图, 那么在此过程中, 其他事务提交了, 那么就会影响新创建的读视图的min_try_id 和m_ids, 使得提交的数据对于当前事务可见, 而可重复读是在事务启动时创建一个读视图, 整个过程中都用这一个读视图, 在此期间, 其他事务提交了, 对于当前事务也是不可见的

Oracle的MVCC

​ Oracle也是通过回滚段来实现MVCC的, 但oracle的实现更复杂,更精细一些。

Oracle相对MySQL的Innodb有几个重点区别

  • Oracle中也有事务ID, 但不是递增的Undo Segment Number ( 回滚段 Number )+Transaction Table Slot Number ( 槽 Number ) +Wrap ( 槽重用次数), 所以不能通过事务id来判断事务的执行前后
  • 事务信息并不是记录在每个数据行上的,而是在块头中的ITL槽上,所以相对来说更省空间

在这里插入图片描述

  • ITL 槽存在数据块头部
  • 每条记录的头部会有一个字节的数据表示使用了哪一个ITL槽 ( ITL 槽最大255 个)
  • 因为Oracle数据库的事务ID不能判断事务的执行前后, 所以为了判断事务的执行前后引入了一个叫SCN的单调递增的序号

版本链

在这里插入图片描述

  • Oracle的回滚信息是存在ITL槽中的, 每条记录的头部会有一个字节的数据表示使用了哪一个ITL槽, 通过这个ITL槽里的回滚指针, 就可以找到旧版本数据
  • 在回滚段的数据会将旧的ITL槽和数据一起存, 这样就形成了版本链

PostgreSQL的MVCC

​​    PostgreSQL数据库的MVCC不同于基于版本链的MVCC, 是没有回滚段的, 旧数据是存放在原有数据文件中的

  • 为了清理旧数据有一个垃圾回收操作vacuum来做这个事。 同时还有有自动垃圾回收autovacuum
  • 更新操作中新行的物理位置发生了变化使用了HOT技术。如果原有的数据块之间有空间,旧行与新行之间会建一个链接,索引上仍然指向旧的数据行。

MVCC实现

  • 每行上有xmin和xmax两个系统字段, 当插入一行数据时,将这行上的xmin设置为当前的事务id,而xmax设置为0
  • 当更新一行时,实际上是插入新行,把旧行上的xmax设置为当前事务id,新插入行的xmin设置为当前事务id,新行的xmax设置为0
  • 当删除一行时,把当前行的xmax设置为当前事务id
  • 当读到一行时,到commitlog ( 记录事务是提交还是回滚 ) 中查询xmin和xmax对应的事务状态是否是己提交还是回滚了,就能判断出此行对当前行是否是可见。

在这里插入图片描述

可见性判断

​    类似MySQL的innodb, PostgreSQL在执行一条SQL也会生成一个快照, 这里是SnapshotData的数据结构, 里面有几个重点字段

  • xmin : 己完成的的最大事务
  • xmax : 未开始的事务
  • xip : 当前数据库中活动的事务id集合

那么对于一条数据

  • 如果数据中的xmin>SnapshotData.xmax 说明这条数据是在当前事务之后的事务插入的, 那么对当前事务不可见
  • 如果数据中的xmin在SnapshotData.xip中, 说明插入这条数据的事务还未提交, 那么对于当前事务不可见
  • 如果数据中的xmin<SnapshotData.xmin, 说明插入这条数据的事务在当前事务之前, 那么就去commit log中查看该事务的状态, 如果是回滚, 则不可见, 如果是提交, 那么接下来看xmax
    • 如果xmax==0 || xmax in SnapshotData.xip 说明这条数据是当前事务执行前的最新版, 对当前事务可见
    • 如果xmax<SnapshotData.xmin 说明可能存在更新的版本或该数据被删除, 那么就去commit log中查看该xmax的事务的状态, 如果是回滚, 那么对当前事务可见, 如果是提交, 说明有更新的版本或者被删除, 那么这条就对当前事务不可见

特点

  • 事务回滚可以立即完成,无论事务进行了多少操作, 数据可以进行很快更新
  • 旧版本数据需要清理,有autovacuum进程vacuum命令处理

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FAST-LIO笔记

1.FAST-LIO FAST-LIO 是一个计算效率高、鲁棒性强的激光-惯性里程计系统。该系统通过紧耦合的迭代扩展卡尔曼滤波器&#xff08;IEKF&#xff09;将激光雷达特征点与IMU数据进行融合&#xff0c;使其在快速运动、噪声较大或环境复杂、存在退化的情况下仍能实现稳定的导航。 1…

C++并发编程完全指南:从基础到实践

在当今多核处理器普及的时代&#xff0c;充分利用硬件并发能力已成为高性能编程的关键。C11引入的现代并发编程支持使得开发者能够以标准化、可移植的方式编写多线程程序。本文将全面介绍C并发编程的各个方面&#xff0c;从基础概念到实际应用&#xff0c;帮助您掌握这一重要技…

如何使用docker配置ros-noetic环境并使用rviz,gazebo

参考链接&#xff1a;【Ubuntu】Docker中配置ROS并可视化Rviz及Gazebo_docker ros-CSDN博客 前言&#xff1a; 其实这个东西是相当必要的&#xff0c;因为我们有时候需要在一台电脑上跑好几个项目&#xff0c;每个项目都有不同的依赖&#xff0c;这些依赖冲突搞得人头皮发麻&…

使用 Java 11 的 HttpClient 处理 RESTful Web 服务

在现代 Web 开发中,与 RESTful Web 服务交互是一项核心任务。Java 作为一种广泛使用的编程语言,提供了多种处理 HTTP 请求的方法。在 Java 11 之前,开发者通常使用 HttpURLConnection 或第三方库(如 Apache HttpClient)。然而,这些方法要么过于底层,要么需要额外依赖。J…

JVM——垃圾回收

垃圾回收 在Java虚拟机&#xff08;JVM&#xff09;的自动内存管理中&#xff0c;垃圾回收&#xff08;Garbage Collection, GC&#xff09;是其核心组件之一。它负责回收堆内存中不再使用的对象所占用的内存空间&#xff0c;以供新对象的分配使用。下面我们将深入探讨JVM中的…

经典密码学算法实现

# AES-128 加密算法的规范实现&#xff08;不使用外部库&#xff09; # ECB模式S_BOX [0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B,0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0x…

追踪大型语言模型的思想(下)(来自针对Claude的分析)

多步推理 正如我们上面所讨论的&#xff0c;语言模型回答复杂问题的一种方式就是简单地记住答案。例如&#xff0c;如果问“达拉斯所在州的首府是哪里&#xff1f;”&#xff0c;一个“机械”的模型可以直接学会输出“奥斯汀”&#xff0c;而无需知道德克萨斯州&#xff0c;达拉…

【Hive入门】Hive增量数据导入:基于Sqoop的关系型数据库同步方案深度解析

目录 引言 1 增量数据导入概述 1.1 增量同步与全量同步对比 1.2 增量同步技术选型矩阵 2 Sqoop增量导入原理剖析 2.1 Sqoop架构设计 2.2 增量同步核心机制 3 Sqoop增量模式详解 3.1 append模式&#xff08;基于自增ID&#xff09; 3.2 lastmodified模式&#xff08;基…

[Windows] 蓝山看图王 1.0.3.21021

[Windows] 蓝山看图王 链接&#xff1a;https://pan.xunlei.com/s/VOPejo0dRLFd38dbpR7XA6djA1?pwddq9v# 由蓝山软件出品的一款免费高清看图软件&#xff0c;支持快速查看高清大图&#xff0c;支持大部分市面图片格式。 软件特点 1、体积小巧&#xff0c;图像显示效果清晰…

通配符 DNS 记录:应用场景与相关风险

随着组织的互联网基础设施不断扩展&#xff0c;其对配置、设置和决策的需求也随之增加——从选择一个可靠的名称服务器&#xff0c;到确定合适的 DNS 记录类型以及设置合适的 TTL&#xff08;生存时间&#xff09;值。其中一项关键决策就是是否要创建通配符 DNS 记录&#xff0…

快速上手知识图谱开源库pykeen教程指南(一)

文章目录 1 前情提要1.1 AmpliGraph 和 PyKEEN 对比介绍1.2 TransE、ConvE、RotatE几款模型的差异 2 直接上案例2.1 数据载入&#xff1a;TriplesFactory2.2 模型训练2.2.1 训练信息2.2.2 TransE模型可以降维实体、关系的关系 2.3 模型保存与加载、评估2.3.1 保存与模型加载2.3…

飞搭系列 | 获取弹窗数据,轻松实现回填

前言 飞搭低代码平台&#xff08;FeiDa&#xff0c;以下简称“飞搭”&#xff09;&#xff0c;为企业提供在线化、灵活的业务应用构建工具&#xff0c;支持高低代码融合&#xff0c;助力企业低门槛、高效率和低成本地快速应对市场变化&#xff0c;加速复杂业务场景落地。 概要…

Linux如何安装AppImage程序

Linux如何安装AppImage程序 文章目录 Linux如何安装AppImage程序 在 Linux 中&#xff0c;.AppImage 是一种便携式的应用程序格式&#xff0c;无需安装即可运行。 1.赋予该文件可执行权限 可以使用下列命令&#xff0c;赋予可执行权限 # 举个例子 chmod x /path/to/MyApp.App…

云硬盘的原理

云硬盘是云计算环境中的一种存储服务&#xff0c;其原理主要涉及数据存储、数据冗余与容错、性能优化以及数据安全等方面&#xff0c;以下是具体介绍&#xff1a; 数据存储 逻辑卷管理&#xff1a;云硬盘通常会将物理存储设备划分为多个逻辑卷&#xff0c;每个逻辑卷可以独立地…

使用 pgrep 杀掉所有指定进程

使用 pgrep 杀掉所有指定进程 pgrep 是一个查找进程 ID 的工具&#xff0c;结合 pkill 或 kill 命令可以方便地终止指定进程。以下是几种方法&#xff1a; 方法1&#xff1a;使用 pkill&#xff08;最简单&#xff09; pkill 进程名例如杀掉所有名为 “firefox” 的进程&…

堆排序(算法题)

#include <bits/stdc.h> using namespace std;const int N 100010; // 堆数组的最大容量 int h[N], s; // h[]存储堆元素&#xff0c;s表示当前堆的大小// 下沉操作&#xff1a;调整以i为根的子树&#xff0c;维护小顶堆性质 void down(int i) {int t i; /…

极狐GitLab 如何将项目共享给群组?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 共享项目和群组 (BASIC ALL) 在极狐GitLab 16.10 中&#xff0c;更改为在成员页面的成员选项卡上显示被邀请群组成员&#xf…

用 CodyBuddy 帮我写自动化运维脚本

我正在参加CodeBuddy「首席试玩官」内容创作大赛&#xff0c;本文所使用的 CodeBuddy 免费下载链接&#xff1a;腾讯云代码助手 CodeBuddy - AI 时代的智能编程伙伴”。 #CodeBuddy首席试玩官 背景 我个人是非常喜欢 Jenkins 自动化部署工具的&#xff0c;之前都是手写 Jenki…

基于windows安装MySQL8.0.40

基于windows安装MySQL8.0.40 基于windows 安装 MySQL8.0.40&#xff0c;解压文件到D:\mysql-8.0.40-winx64 在D:\mysql-8.0.40-winx64目录下创建my.ini文件&#xff0c;并更新一下内容 [client] #客户端设置&#xff0c;即客户端默认的连接参数 # 设置mysql客户端连接服务…

Python小酷库系列:5个常用的dict属性化访问扩展库

5个常用的dict属性化访问扩展库 嵌套结构高级功能性能综合建议 在前面我们详细讲解了 Box和 Munch这两个dict属性化访问的扩展库&#xff0c;总体而言它们主要用于提升配置文件数据、JSON对象数据的可读性&#xff0c;减少了代码中双引号。在这一领域中还有dotmap、addict 和…