Postgresql源码(120)事务XID分配与主备XID同步

参考
《Postgresql源码(25)子事务可见性判断和性能问题》

XID获取顶层入口

函数:AssignTransactionId

static void
AssignTransactionId(TransactionState s)
{...

优先给没有事务ID的父事务分配

确保父事务有 XID,以便子事务总是拥有一个比其父事务更新的 XID。这里不能递归调用,否则如果我们处于一个巨大的子事务堆栈的底部,而这些子事务还没有分配 XID,可能会遇到栈溢出的问题。

下面虽然递归了,但永远不会超过1层。

if (isSubXact && !FullTransactionIdIsValid(s->parent->fullTransactionId)){TransactionState p = s->parent;TransactionState *parents;size_t		parentOffset = 0;parents = palloc(sizeof(TransactionState) * s->nestingLevel);while (p != NULL && !FullTransactionIdIsValid(p->fullTransactionId)){parents[parentOffset++] = p;p = p->parent;}while (parentOffset != 0)AssignTransactionId(parents[--parentOffset]);pfree(parents);}

当 wal_level=logical 时,确保只有在其顶级事务的 xid 已经被记录到 WAL 中之后,子事务的 xid 才能在 WAL 流中被看到。如果必要,会记录一个包含少于PGPROC_MAX_CACHED_SUBXIDS(64个) xact_assignment 记录。

请注意,即使一个事务的didLogXid 没有被设置,而它出现在 WAL 记录中,这也是可以的,我们可能会多余地记录一些内容。当一个 xid 被包含在 wal 记录的内部某处,但不在 XLogRecord->xl_xid 中时,就会发生这种情况,如在 xl_standby_locks 中。

	if (isSubXact && XLogLogicalInfoActive() &&!TopTransactionStateData.didLogXid)log_unknown_top = true;

生成一个新的 FullTransactionId 并在 PGPROC 和 pg_subtrans 中记录其 xid。

注意:必须在 Xid 出现在 PGPROC 之外的任何共享存储中之前,先创建 subtrans 条目;因为如果 PGPROC 中没有空间容纳它,subtrans 条目是必需的,以确保其他后端将 Xid 视为“正在运行”。参见 GetNewTransactionId。

	s->fullTransactionId = GetNewTransactionId(isSubXact);if (!isSubXact)XactTopFullTransactionId = s->fullTransactionId;if (isSubXact)SubTransSetParent(XidFromFullTransactionId(s->fullTransactionId),XidFromFullTransactionId(s->parent->fullTransactionId));...currentOwner = CurrentResourceOwner;CurrentResourceOwner = s->curTransactionOwner;

加xid锁,实现mvcc的功能(事务之间修改同一行数据时用到这个);resowner必须用事务的。

	XactLockTableInsert(XidFromFullTransactionId(s->fullTransactionId));CurrentResourceOwner = currentOwner;

在每个顶级事务中,每分配 PGPROC_MAX_CACHED_SUBXIDS(64)个事务 id,就为分配发出一个 WAL 记录。

这里看最后一章的分析:

	if (isSubXact && XLogStandbyInfoActive()){unreportedXids[nUnreportedXids] = XidFromFullTransactionId(s->fullTransactionId);nUnreportedXids++;...if (nUnreportedXids >= PGPROC_MAX_CACHED_SUBXIDS ||log_unknown_top){xl_xact_assignment xlrec;xlrec.xtop = GetTopTransactionId();Assert(TransactionIdIsValid(xlrec.xtop));xlrec.nsubxacts = nUnreportedXids;XLogBeginInsert();XLogRegisterData((char *) &xlrec, MinSizeOfXactAssignment);XLogRegisterData((char *) unreportedXids,nUnreportedXids * sizeof(TransactionId));(void) XLogInsert(RM_XACT_ID, XLOG_XACT_ASSIGNMENT);nUnreportedXids = 0;TopTransactionStateData.didLogXid = true;}}
}

xid具体获取流程

函数:GetNewTransactionId

32位事务ID:

uint32
0 1 2 3 4 5 ...... 4294967295  →(回卷)
0 1 2 3 4 5 ...... 4294967295  →(回卷)
0 1 2 3 4 5 ...... 4294967295  →(回卷)
0 1 2 3 4 5 ...... 4294967295  →(回卷)
0 1 2 3 4 5 ...... 4294967295  →(回卷)

fullxid使用64b,分成两个32b来使用:

uint64  
[epoch 32bit][xid 32bit][0][0]  [0][1]  [0][2]  [0][3] ..... [0][4294967295]  →(回卷,不在溢出,只需要把epoch加一)
[1][0]  [1][1]  [1][2]  [1][3] ..... [1][4294967295]  →(回卷,不在溢出,只需要把epoch加一)
[2][0]  [2][1]  [2][2]  [2][3] ..... [2][4294967295]  →(回卷,不在溢出,只需要把epoch加一)

但是,在目前版本中(PG15),落盘的表和XLOG里面还是记录的32位XLOG,主要是兼容性问题不好解决。

typedef uint32 TransactionId;typedef struct XLogRecord
{uint32		xl_tot_len;		/* total len of entire record */TransactionId xl_xid;		/* xact id */XLogRecPtr	xl_prev;		/* ptr to previous record in log */uint8		xl_info;		/* flag bits, see below */RmgrId		xl_rmid;		/* resource manager for this record *//* 2 bytes of padding here, initialize to zero */pg_crc32c	xl_crc;			/* CRC for this record *//* XLogRecordBlockHeaders and XLogRecordDataHeader follow, no padding */} XLogRecord;

子事务ID维护

函数:SubTransSetParent
《Postgresql源码(25)子事务可见性判断和性能问题》

主机为什么每64个subxid就给备机发送一批?

结论

  • 主库给备库同步正在运行的xid列表,缓冲64个一批发过去,避免频率太高。
  • 备库收到后会挑一个最大的xid做记录RecordKnownAssignedTransactionIds。
  • 备库会把除了最大的都删了,因为备库可以根据最大值推测其他运行中的xid。

分析
在备机redo时,ProcArrayApplyXidAssignment负责处理收到的xids日志。

xact_redo...else if (info == XLOG_XACT_ASSIGNMENT){xl_xact_assignment *xlrec = (xl_xact_assignment *) XLogRecGetData(record);if (standbyState >= STANDBY_INITIALIZED)ProcArrayApplyXidAssignment(xlrec->xtop,xlrec->nsubxacts, xlrec->xsub);}

包含了两部分:

  • xlrec->xtop:顶层事务ID
  • xlrec->xsub:子事务IDs

ProcArrayApplyXidAssignment函数负责处理:

ProcArrayApplyXidAssignment(TransactionId topxid,int nsubxids, TransactionId *subxids)
{...max_xid = TransactionIdLatest(topxid, nsubxids, subxids);

最大的子事务ID记一下就好啦,其他的备库能推测出来。

	RecordKnownAssignedTransactionIds(max_xid);

注意这里,主库的标记逻辑是
SubTransSetParent(XidFromFullTransactionId(s->fullTransactionId), XidFromFullTransactionId(s->parent->fullTransactionId));
父子事务会形成链式结构,需要查询子事务最终状态需要遍历到最后一个。
原因是要实现rollback to的逻辑,必须将事务维护成chain的结构,rollback to会按顺序影响多个子事务。

而备库的逻辑是直接全部挂在顶层事务上,因为备库redo时:

  1. 完全不关心子事务的关系,可见性判断交给快照和xid就足够了。
  2. 那怎么知道sub xid是不是提交了?
    • 情况1:sub xid的事务回滚了,那么主库会立即写clog,备库立即就知道了。
    • 情况2:sub xid的事务提交了,主库不会立即通知备库,直到顶层事务commit或release。所以这种情况下,把sub xid直接挂到顶层事务上是没有问题的,refer directly to the top-level transaction’s state。
	for (i = 0; i < nsubxids; i++)SubTransSetParent(subxids[i], topxid);...

记录完了最大的,里面其他的就可以删了。

	KnownAssignedXidsRemoveTree(InvalidTransactionId, nsubxids, subxids);if (TransactionIdPrecedes(procArray->lastOverflowedXid, max_xid))procArray->lastOverflowedXid = max_xid;...
}

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

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

相关文章

倒计时65天

复习2。 一.╥﹏╥...倒计时72天╥﹏╥...-CSDN博客 1.* #include<bits/stdc.h> using namespace std; #define int long long const int N3e35; const int inf0x3f3f3f3f; int a[N][N],b[N][N]; void solve() {int n;cin>>n;for(int i1;i<n;i){for(int j1;j…

Spring Boot 依赖管理:spring-boot-dependencies vs spring-boot-starter-parent

在Spring Boot项目中&#xff0c;有多种方式来管理和配置依赖&#xff0c;本文将详细解析两种主要的依赖配置方法——通过spring-boot-dependencies与spring-boot-starter-parent&#xff0c;并分析它们各自的优缺点以指导开发者的实际应用。 1. spring-boot-dependencies 的使…

全流程机器视觉工程开发(四)PaddleDetection C++工程化应用部署到本地DLL以供软件调用

前言 我们之前跑了一个yolo的模型&#xff0c;然后我们通过PaddleDetection的库对这个模型进行了一定程度的调用&#xff0c;但是那个调用还是基于命令的调用&#xff0c;这样的库首先第一个不能部署到客户的电脑上&#xff0c;第二个用起来也非常不方便&#xff0c;那么我们可…

Java八大常用排序算法

1冒泡排序 对于冒泡排序相信我们都比较熟悉了&#xff0c;其核心思想就是相邻元素两两比较&#xff0c;把较大的元素放到后面&#xff0c;在一轮比较完成之后&#xff0c;最大的元素就位于最后一个位置了&#xff0c;就好像是气泡&#xff0c;慢慢的浮出了水面一样 Jave 实现 …

2024 RTE行业(实时互动行业)人才发展学习总结

解决方案 人才画像 开发者人才素质要求&#xff1a; 具备多个领域的技术知识注重团队合作&#xff0c;具备协作能力以用户为导向的用户体验意识具备创新思维和解决问题的能力需快速响应行业变化和持续的学习能力具备项目管理能力 学习和吸收新知识的渠道 RTE人才分类

操作系统透视:从历史沿革到现代应用,剖析Linux与网站服务架构

目录 操作系统 windows macos Linux 服务器搭建网站 关于解释器的流程 curl -I命令 名词解释 dos bash/terminal&#xff0c;(终端) nginx/apache&#xff08;Linux平台下的&#xff09; iis&#xff08;Windows平台下的&#xff09; GUI(图形化管理接口&#xff…

开源软件之光:促进创新与协作的引擎(AI)

开源软件之光&#xff1a;促进创新与协作的引擎 引言开源软件的定义开源软件的推动力 1. 创新的温床2. 协作的桥梁3. 自由的理念 开源软件对软件行业的影响 1. 业务模式的革新2. 技术水平的提升3. 标准的制定 开源软件对社会的深远影响 1. 数字包容性的推动者2. 共享文化的倡导…

【51单片机系列】应用设计——8路抢答器的设计

51单片机应用——8路抢答器设计 文章设计文件及代码&#xff1a;资源链接。 文章目录 要求&#xff1a;设计思路软件设计仿真结果 要求&#xff1a; &#xff08;1&#xff09; 按下”开始“按键后才开始抢答&#xff0c;且抢答允许指示灯亮&#xff1b; &#xff08;2&…

聚道云软件连接器助力餐饮企业实现数字化管理

客户介绍 某餐饮有限责任公司是一家历史悠久、口碑良好的连锁餐饮公司。公司总部位于北京市&#xff0c;拥有多家门店&#xff0c;覆盖了北京市内的各个区域。每家门店都以独特的装修风格和优雅的环境为顾客营造温馨舒适的用餐氛围。作为一家知名的连锁餐饮公司&#xff0c;在…

过好“苏州年”!沉浸式名城非遗文化体验展 2月10日正式启幕

擦亮非遗文化底色&#xff0c;绘就历史文化名城金名片 天工开画卷&#xff0c;苏作见匠心&#xff0c;在2024龙年到来之际&#xff0c;“匠海拾遗-沉浸式名城非遗文化体验展” 将于2月10日在江苏省省级文物保护单位——江苏按察使署旧址内举办。此次非物质文化遗产&#xff08;…

QT Creator 的代码重构工具

在 QT Creator 中&#xff0c;重构菜单提供了许多强大的重构工具&#xff0c;可以帮助你改进代码的结构和可读性。重构菜单通常包含以下选项&#xff1a; Extract Function&#xff1a;将当前函数或方法内的代码提取为新的函数或方法&#xff0c;并自动更新所有引用。Rename S…

记录Git无法连接Github(443报错)的一种可能——代理问题

参考文章&#xff1a; Git安装配置与使用&#xff08;超级详细&#xff09;_git配置-CSDN博客 github代理报错_valueerror: unable to determine socks version from-CSDN博客 速通 如果在使用 git 时遇到了这样的报错&#xff1a; OpenSSL SSL_connect: SSL_ERROR_SYSCAL…

机器学习周报第二十八周 PINNs2

文章目录 week28 PINNs2摘要Abstract一、Lipschitz条件二、文献阅读1. 题目数据驱动的偏微分方程2. 连续时间模型3. 离散时间模型4.结论 三、CLSTM1. 任务要求2. 实验结果3. 实验代码3.1模型构建3.2训练过程代码 小结参考文献 week28 PINNs2 摘要 本文主要讨论PINN。本文简要…

机器学习 | 解析聚类算法在数据检测中的应用

目录 初识聚类算法 聚类算法实现流程 模型评估 算法优化 特征降维 探究用户对物品类别的喜好细分(实操) 初识聚类算法 聚类算法是一种无监督学习方法&#xff0c;用于将数据集中的对象按照相似性分组。它旨在发现数据中的内在结构和模式&#xff0c;将具有相似特征的数据…

MySQL进阶之锁(行锁,间隙锁,临键锁)

行级锁 介绍 行级锁&#xff0c;每次操作锁住对应的行数据。锁定粒度最小&#xff0c;发生锁冲突的概率最低&#xff0c;并发度最高。应用在 InnoDB存储引擎中。 InnoDB的数据是基于索引组织的&#xff0c;行锁是通过对索引上的索引项加锁来实现的&#xff0c;而不是对记录加…

Linux——权限管理

1、ACL权限 在普通权限中&#xff0c;用户对文件只有三种身份&#xff0c;就是属主、属组和其他人&#xff1b;每种用户身份拥有读&#xff08;read&#xff09;、写&#xff08;write&#xff09;和执行&#xff08;execute&#xff09;三种权限。但是在实际工作中&#xff0…

神界原罪2武器伤害期望参考

前提 不讨论命中率&#xff08;一般不缺命中率&#xff09; 默认吃到高地伤害加成 某些天赋的增伤&#xff08;如元素游侠&#xff09;由于比较特殊且不影响点数分配&#xff0c;故伤害公式中没有体现 计算结果只为理论数值&#xff0c;具体伤害还要受怪物抗性、地形、buff等多…

如何选择Centos的替代者

开篇废话&#xff1a;许久许久没有更新博客了。寒假回到故土&#xff0c;大雪虽然没有封路&#xff0c;还是增加了不出门的决心&#xff0c;虽然年岁已高&#xff0c;但是不学习还是不踏实&#xff0c;那就借着写作再继续前行。 背景&#xff1a;信息化部门&#xff0c;掌管着…

uniapp使用u-popup组件弹窗出现页面还可滑动

*1、问题所在&#xff1a; 弹窗遮罩层出现了页面依旧可以上下滑动 2、要求: 为了用户更好交互体验&#xff0c;弹窗出现后应禁止页面往下滑动 3、实现思路&#xff1a; 在弹窗盒子外层添加个阻止触摸冒泡事件&#xff0c;使用touchmove.stop.prevent 4、代码如下&#xff…

Django学习记录01

1.项目结构 djangoProject02 ├── manage.py 【项目的管理&#xff0c;启动项目、创建app、数据管理】【不要动】【常常用】 └── jangoProject02 ├── __init__.py ├── settings.py 【项目配置】 【常常修改】 ├── urls.py …