PostgreSQL技术内幕11:PostgreSQL事务原理解析-MVCC

news2024/12/26 20:51:50

文章目录

    • 0.简介
    • 1.MVCC介绍
    • 2.MVCC常见的实现方式
    • 3.PG的MVCC实现
      • 3.1 可见性判断
      • 3.2 提交/取消

0.简介

本文主要介绍在事务模块中MVCC(多版本并发控制)常见的实现方式,优缺点以及PG事务模块中MVCC(多版本并发控制)的实现。

1.MVCC介绍

MVCC(Multi-Version Concurrency Control,多版本并发控制)是一种用于数据库管理系统中的并发控制的方法。在传统的并发控制中,常用的简单方式是通过加锁来保证某一时刻数据只被一个事务修改,但这种方式可能会带来并发度的下降,尤其在高并发场景下,很可能导致性能瓶颈。MVCC主要通过维护数据的多个版本来解决传统锁机制的一些局限性,每个事务可以看到一个特定版本,从而使得读写操作可以互不干扰地执行,其核心在于,对于每个修改,不直接在原始数据上修改,而是创建一个新的数据版本来做修改,其他事务依然可以访问旧的数据,以此来提高并发度。当然MVCC也有其局限性,比如在高并发场景下可能因为多个版本导致占用较高内存。

2.MVCC常见的实现方式

MVCC常见的实现方式有两种:
1)修改旧数据前备份,在写新的数据时,把旧的数据备份到单独的一块空间,其他事务读取数据时,可以在备份空间中获取,比如MySQL innodb引擎的回滚段。
2)新数据不直接修改,而是采用插入的方式。
以上两种方式,功能上都能实现MVCC,都需要占用一定的空间,两者相比较,二的事务回滚更为方便,不会出现备份空间用尽的问题;一的话清理上会更为简单,不会导致数据扫描使得读数据增加。PG采用的是二,即采用插入方式实现的MVCC。

3.PG的MVCC实现

3.1 可见性判断

MVCC的实现,首先要有版本的概念,下面来看PG中的定义,然后以一个实际的例子来分析可见性的判断,定义如下:

typedef struct HeapTupleFields
{
  TransactionId t_xmin;    /* inserting xact ID */
  TransactionId t_xmax;    /* deleting or locking xact ID */

  union
  {
    CommandId  t_cid;    /* inserting or deleting command ID, or both */
    TransactionId t_xvac;  /* old-style VACUUM FULL xact ID */
  }      t_field3;
} HeapTupleFields;

struct HeapTupleHeaderData
{
  union
  {
    HeapTupleFields t_heap;
    DatumTupleFields t_datum;
  }      t_choice;

  ItemPointerData t_ctid;    /* current TID of this or newer tuple (or a
                 * speculative insertion token) */
  ....
}

可以看到,在上面代码结构中,每个元组头部存储事务的t_xmin(数据插入的事务id),t_xmax(数据删除或更新的事务id)如果为0则表示还未被删除和更新,这两个值一旦被设计就不会再次变化。
下面通过一个例子来看一个更新操作的修改以及可见性的判断。
在这里插入图片描述
上述描述了向当前表插入了一条数据的过程,初始a=2,b=2的记录是由事务id为10的事务插入,xmax为0即还没被删除或更新;然后执行update语句,将a的值设置为6,xmax的值更新为11(表示由id为11的事务删除),同时新增一条记录(不在原记录修改),此时虽然有两条数据,但其实应该只有一条,所以需要根据事务的快照和提交的记录来进行判断,也就是可见性的判断。
在PG中,是用snapshot来获取那些事务正在执行,通过snapshot来区分事务是正在执行还是已经完成了,如果事务尚未完成,那么事务的更新和写入对其他事务来说是不可见的。snapshot数据结构如下:

typedef struct SnapshotData
{
  SnapshotSatisfiesFunc satisfies;  /* tuple test function */
  TransactionId xmin;      /* all XID < xmin are visible to me */
  TransactionId xmax;      /* all XID >= xmax are invisible to me */

  TransactionId *xip;
  uint32    xcnt;      /* # of xact ids in xip[] */

  TransactionId *subxip;
  int32    subxcnt;    /* # of xact ids in subxip[] */
  bool    suboverflowed;  /* has the subxip array overflowed? */

  bool    takenDuringRecovery;  /* recovery-shaped snapshot? */
  bool    copied;      /* false if it's a static snapshot */

  CommandId  curcid;      /* in my xact, CID < curcid are visible */

  uint32    speculativeToken;

  uint32    active_count;  /* refcount on ActiveSnapshot stack */
  uint32    regd_count;    /* refcount on RegisteredSnapshots */
  pairingheap_node ph_node;  /* link in the RegisteredSnapshots heap */

  TimestampTz whenTaken;    /* timestamp when snapshot was taken */
  XLogRecPtr  lsn;      /* position in the WAL stream when taken */
} SnapshotData;

其中所有XID<xmin(已完成的)的事务都可见,所有XID>xmax的事务都不可见,而介于xmin和xmax之间的事务可能已完成也可能进行中,所以需要一个数组来存储(xip),如果在xmin和xmax之间的事务id在这个数组被发现,说明事务正在进行且尚未完成,不可见。
获取数据时,会先根据snapshot来判断事务是否已完成,如果未完成,则不可见,对于已完成的需要判断时提交还是取消,查询clog来进行判断。这里还有个性能优化,就是使用tuple中标志位来进行判断,减少clog查询。

3.2 提交/取消

在PG中,一个事务最终状态可能有两种:Commit/Abort。
1)Commit:提交时会写WAL和CLOG,提交后对于其他事务可见。
2)Abort: abort时会写WAL和CLOG,abort后对于其他事务不可见。

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

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

相关文章

1×1卷积核【super star 卷积核】

一、11卷积的作用 我们先来给出11卷积的一般作用&#xff0c;如下所示&#xff1a; • 跨通道的特征整合 • 特征通道的升维与降维 • 减少权重参数&#xff08;卷积核参数&#xff09; 【 简化模型 】 1.1 特征通道的升维与降维/跨通道的特征整合/简化模型 输入数据&…

【Transformer深入学习】之一:Sinusoidal位置编码的精妙

看苏神的文章提到&#xff1a;Transformer原论文使用Sinusoidal位置编码&#xff0c;作为位置编码的一个显式解&#xff0c;Google 在原论文中对它的描述寥寥无几&#xff0c;只是简单提及了它可以表达相对位置信息&#xff0c;并未提及这个编码的合理性。 看了几篇文章&#x…

JAVA零基础入门——面向对象

1.继承 1.1 继承概念 继承的概念&#xff1a;继承就是子类继承父类的特征和行为&#xff0c;使得子类对象&#xff08;实例&#xff09;具有父类的实例域和方法&#xff0c;或子类从父类继承方法&#xff0c;使得子类具有父类相同的行为。我们将"继承概念"分为两类:…

WINDOWS AGENTARENA:EVALUATING MULTI-MODAL OS AGENTS AT SCALE论文学习

文章开头说现有的agent都是局限于特定领域&#xff08;什么网络问答啊&#xff0c;仅限文字啊&#xff0c;仅限于某一个app啊&#xff09;这样的&#xff0c;本文的工作主打一个贴近用户使用场景&#xff0c;用户用什么软件&#xff0c;看什么网页&#xff0c;本文的模型就用什…

Sapiens——人类视觉大模型的基础

引言 大规模预训练以及随后针对特定任务的语言建模微调取得了显著成功&#xff0c;已将这种方法确立为标准做法。同样&#xff0c; 计算机视觉方法正逐步采用大规模数据进行预训练。LAION5B、Instagram-3.5B、JFT-300M、LVD142M、Visual Genome 和 YFCC100M 等大型数据集的出现…

Python 实现Excel XLS和XLSX格式相互转换

在日常工作中&#xff0c;我们经常需要处理和转换不同格式的Excel文件&#xff0c;以适应不同的需求和软件兼容性。Excel文件的两种常见格式是XLS&#xff08;Excel 97-2003&#xff09;和XLSX&#xff08;Excel 2007及以上版本&#xff09;。本文将详细介绍如何使用Python在XL…

【SQLite数据库常规使用命令】

之前在做围绕数据库相关的一些小工具的时候&#xff0c;想找一款数据库作为小工具的资料库。需求是&#xff1a;不用复杂的安装&#xff0c;支持简单SQL&#xff0c;空间占用小&#xff0c;操作简单等等。 结合着之前接触到的一些研发同事做的产品的使用经验&#xff0c;我想到…

递归7小题

[ 注意&#xff1a;前6道题均是使用递归完成的&#xff0c;需要数组、指针、链表相关知识&#xff0c;第7道题是求水仙花数的加强版&#xff0c;也是使用递归完成的&#xff0c;3位数的水仙花数我们很熟悉&#xff0c;那5位数的呢&#xff1f;7位数的呢&#xff1f;9位数的呢&a…

【pycharm】如何两个窗口打开同一代码

文章目录 前言解决方案结果 前言 在 编辑长代码&#xff0c;要看上下离得较远的变量 时遇到的问题 解决方案 “window” → “Editor Tabs” → “Split right" 结果

CleanClip vs 传统剪贴板:究竟谁更胜一筹?

在日常工作和生活中,复制粘贴可以说是我们使用最频繁的操作之一。传统的剪贴板功能虽然简单易用,但在功能性和效率上还有很大的提升空间。今天,我们就来比较一下新兴的剪贴板增强工具CleanClip与传统剪贴板,看看到底谁更胜一筹。 1. 剪贴历史管理 传统剪贴板只能存储最后一次…

动态线程池实战(一)

动态线程池 对项目的认知 为什么需要动态线程池 DynamicTp简介 接入步骤 功能介绍 模块划分 代码结构介绍

设计模式学习[6]---代理模式

文章目录 前言1.原理阐述2.举例2.1 例子与类图2.2 代码 总结 前言 代理这个词&#xff0c;从小到大听过不少。比如什么代理服务器&#xff0c;代理商&#xff0c;代理人之类的。通俗来说&#xff0c;代理无非无非就是我代表你处理事务的意思。 那么在设计模式中&#xff0c;针…

Android WebView H5 Hybrid 混和开发

对于故乡&#xff0c;我忽然有了新的理解&#xff1a;人的故乡&#xff0c;并不止于一块特定的土地&#xff0c;而是一种辽阔无比的心情&#xff0c;不受空间和时间的限制&#xff1b;这心情一经唤起&#xff0c;就是你已经回到了故乡。——《记忆与印象》 前言 移动互联网发展…

智能车镜头组入门(三)巡线

镜头组的特点是通过摄像头来获取赛道的信息&#xff0c;从而达到前瞻的效果&#xff0c;完成转向和速度决策。 我们的方案&#xff0c;带上元素识别&#xff0c;大概在TC264上5ms一帧&#xff0c;所以我们开了100hz的图象。 之前我看别的博客上有人说&#xff0c;他们组的50帧…

MyBatis框架SqlSession浅析

1、SqlSessionFactory作用 MyBatis框架SqlSessionFactory是线程安全的&#xff0c;负责创建SqlSession。 DefaultSqlSessionFactory是线程安全的&#xff0c;属性Final。 2、SqlSessionFactoryBuilder SqlSessionFactoryBuilder负责创建SqlSessionFactory。SqlSessionFactory…

C++伟大发明--模版

C起初是不受外界关注的&#xff0c;别人觉得他和C语言没有本质上的区别&#xff0c;只是方便些&#xff0c;直到祖师爷发明了模版&#xff0c;开始和C语言有了根本的区别。 我们通过一个小小的例子来搞清楚什么是模版&#xff0c;模版的作用到底有多大&#xff0c;平时我们想要…

UAC2.0 麦克风——类特殊请求

UAC2.0 麦克风枚举过程参考 UAC2.0 麦克风——单声道 USB 麦克风(16bit) 文章目录 set interfaceget device status类特殊请求get curget rangevolume rangesample rangeset interface USB 请求代码 typedef enum {USB_REQ_GET_STATUS = 0 ,USB_REQ_CLEAR_FEATURE …

自动化中验证码的操作笔记,懂的赶紧收藏!

在自动化测试的过程中&#xff0c;验证码一直被视为一个“拦路虎”。很多测试人员在做接口或UI自动化时都会遇到验证码的阻碍&#xff0c;导致测试无法继续进行。今天&#xff0c;我们就来讨论如何在自动化过程中破解验证码&#xff0c;快速绕过这道关卡&#xff0c;轻松完成自…

【C51】独立按键控制LED灯

1.简介 在单片机应用系统中&#xff0c;常常使用轻触按键组成键盘。轻触按键具有自动回弹的特点&#xff0c;即按下按键&#xff0c;两个触点接通&#xff0c;放开按键&#xff0c;两个触点断开。轻触按键的外形及电路符号如图&#xff0c;通常轻触按键有4个引脚&#xff0c;4个…

Redis - 深入理解Redis事务

目录 Redis是如何实现事务的&#xff1f;事务中执行的命令出现错误&#xff0c;会回滚事务吗&#xff1f;同一个连接可以重复开启事务吗&#xff1f;多个客户端同时开启事务会怎样&#xff1f;使用Redis事务只用MULTI和EXEC吗&#xff1f;Redis中的WATCH机制是怎么实现的&#…