Postgresql源码(100)Portal与事务的关系(顶层事务与子事务)
1 总结
-
portal与事务有强绑定的关系,由portal->createSubid变量记录关联关系。如果为1表示顶层事务,关联的是子事务。
-
不论是顶层事务还是子事务,提交、回滚时只会处理自己创建出来的portal。
- 顶层事务会清理非活跃状态的Portal,如果Portal是活跃的会保留内存。
- 子事务直接释放portal,无论是否活跃。
-
PLpgSQL中的提交回滚,有较大限制:
- PLpgSQL中的提交或回滚,如果call proc在事务块中,直接失败。
- PLpgSQL中的提交或回滚,如果pl带exception,直接失败。
- 原因是,pl中的提交或回滚不能再子事务、或事务块内,要实现的话比较复杂,需要对齐SPI与子事务、portal与子事务、exprcontext与子事务等等。
-
子事务ID只增不减,可能有空隙存在,参考PushTransaction的currentSubTransactionId。
2 提交
2.1 顶层事务提交:PreCommit_Portals与子事务提交AtSubCommit_Portals
实例
CREATE OR REPLACE PROCEDURE tproc1()
AS $$
DECLAREcurs1 refcursor; curs2 CURSOR FOR SELECT c1 FROM tf1;curs3 CURSOR (key integer) FOR SELECT * FROM tf1 WHERE c1 > key;x int;y tf1%ROWTYPE;
BEGINopen curs1 FOR SELECT * FROM tf1 WHERE c1 > 3;fetch curs1 into y; RAISE NOTICE 'curs1 : %', y.c3;fetch curs1 into y; RAISE NOTICE 'curs1 : %', y.c3;open curs2;fetch curs2 into x; RAISE NOTICE 'curs2 : %', x;fetch curs2 into x; RAISE NOTICE 'curs2 : %', x;OPEN curs3(4); -- OPEN curs3(key := 4);fetch curs3 into y; RAISE NOTICE 'curs3 : %', y.c4;fetch curs3 into y; RAISE NOTICE 'curs3 : %', y.c4;
EXCEPTION WHEN others THENRAISE NOTICE 'in caller exception';
END;
$$ LANGUAGE plpgsql;begin;
savepoint sp1;
savepoint sp2;
call tproc1();
commit;
(1)第一次子事务提交:EXCEPTION子事务提交AtSubCommit_Portals(subid=4)
发生在call tproc1();执行完毕。
exec_stmt_blockReleaseCurrentSubTransactionCommitSubTransactionAtSubCommit_Portals
当前事务堆栈:
CurrentTransactionState->subTransactionId
[1, 2, 3, 4]| | | |
top savepoint savepoint exception
由于call进入SPI,当前SPI堆栈只有一层,对应到3号子事务上,因为是在3号子事务的背景下执行的CALL。
_SPI_stack[0] = {connectSubid = 3}
AtSubCommit_Portals(mySubid=4) 开始处理portal:
portal1 = { // 游标 mySubid = 4 ,当前游标的portal被继承给parent portalname = "<unnamed portal 17>", createSubid = 4, // AtSubCommit_Portals 4-->3activeSubid = 4,createLevel = 4, sourceText = "SELECT c1 FROM tf1",commandTag = CMDTAG_SELECT,strategy = PORTAL_ONE_SELECT}
… 三个游标的portal都是类似上面处理的。特殊的是顶层portal。不属于当前要释放的子事务4,不处理。
portal1 = { // 顶层 mySubid = 3 ,当前不处理name = "", createSubid = 3, activeSubid = 3, createLevel = 3, sourceText = "call tproc1();",commandTag = CMDTAG_CALL,strategy = PORTAL_MULTI_QUERY}
(2)第二次子事务提交:savepoint子事务提交AtSubCommit_Portals(subid=3)
发生在commit。
exec_simple_queryfinish_xact_commandCommitTransactionCommandCommitSubTransactionAtSubCommit_Portals
当前事务堆栈:
CurrentTransactionState->subTransactionId
[1, 2, 3]| | |
top savepoint savepoint
AtSubCommit_Portals(mySubid=3)开始处理portal:
portal1 = { // 游标 mySubid = 4 ,当前游标的portal被继承给parent portalname = "<unnamed portal 17>", createSubid = 2, // AtSubCommit_Portals 3-->2activeSubid = 2, // AtSubCommit_Portals 3createLevel = 2, // AtSubCommit_Portals 3-->2sourceText = "SELECT c1 FROM tf1",commandTag = CMDTAG_SELECT,strategy = PORTAL_ONE_SELECT}
当前堆栈Portal已经被drop了。现在PortalHashTable里面只有三个游标的Portal。
(3)第三次子事务提交:savepoint子事务提交(subid=2)
同上。
(4)顶层事务提交(subid=1)PreCommit_Portals
发生在commit。
exec_simple_queryfinish_xact_commandCommitTransactionCommandCommitTransactionPreCommit_Portals
提交时发现3个portal,只剩游标的3个portal了。
调用PortalDrop全部释放掉。
PreCommit_Portals函数需要关注的就是,普通portal都会被drop掉。特殊保留的是hold cursor即循环语句使用的内部自建游标,还有一种就是vacuum等多事务语句。
3 回滚
3.1 顶层事务清理:AtAbort_Portals
调用位置
AbortTransaction → AtAbort_Portals
调用一次即可,用户清理顶层事务。
清理逻辑
- 遍历PortalHashTable,拿到所有CreatePortal创建出来的Portal(两种:执行器的portal和游标的portal)
- 标记portal状态failed,标记failed的内存会被释放掉。
- 情况一:elog FATAL 主动标记failed
- 情况二:状态是PORTAL_READY的portal
- 跳过一些portal,不处理。
- 情况一:createSubid=0 前一个事务的portal,不属于自己(!=1)。
- 情况二:portal->autoHeld == true 专门用于循环的游标(不是用户创建的,PL自用的)。
3.2 子事务清理:AtSubAbort_Portals
调用位置
AbortSubTransaction → AtSubAbort_Portals
有两种调用场景:
- 事务块内一次性rollback,递归多次AtSubAbort_Portals,提交所有子事务。
- 回滚到某一个检查点,递归指定次数AtSubAbort_Portals,只提交指定的几个子事务。
清理逻辑
- 遍历PortalHashTable,拿到所有CreatePortal创建出来的Portal(两种:执行器的portal和游标的portal)
- 判断创建归属:
- 如果当前清理的子事务 与 portal的createSubid匹配,直接清理PORTAL_READY和PORTAL_ACTIVE状态的,包括删除内存。
- 如果当前清理的子事务 与 portal的createSubid不匹配:
- 判断使用归属,如果当前清理的子事务 与 portal的activeSubid匹配,说明不是当前子事务创建的,但是被当前子事务使用了,指标记failed但不做清理,不删除内存。
4 PushTransaction与PopTransaction函数
- 启动子事务时需要将当前事务入栈,CurrentTransactionState换成子事务的。
- 子事务和父事务由parent连接。
- 修改这部分代码需要注意一次弹出多个事务时,currentSubTransactionId有没有正确维护。
static void
PushTransaction(void)
{TransactionState p = CurrentTransactionState;TransactionState s;s = (TransactionState)MemoryContextAllocZero(TopTransactionContext,sizeof(TransactionStateData));
注意currentSubTransactionId直增不减。pop时也不减少。
currentSubTransactionId += 1;if (currentSubTransactionId == InvalidSubTransactionId){currentSubTransactionId -= 1;pfree(s);ereport(ERROR,(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),errmsg("cannot have more than 2^32-1 subtransactions in a transaction")));}/** We can now stack a minimally valid subtransaction without fear of* failure.*/s->fullTransactionId = InvalidFullTransactionId; /* until assigned */s->subTransactionId = currentSubTransactionId;s->parent = p;s->nestingLevel = p->nestingLevel + 1;s->gucNestLevel = NewGUCNestLevel();s->savepointLevel = p->savepointLevel;s->state = TRANS_DEFAULT;s->blockState = TBLOCK_SUBBEGIN;GetUserIdAndSecContext(&s->prevUser, &s->prevSecContext);s->prevXactReadOnly = XactReadOnly;s->parallelModeLevel = 0;s->topXidLogged = false;CurrentTransactionState = s;}
相关文章:
Postgresql源码(100)Portal与事务的关系(顶层事务与子事务)
1 总结 portal与事务有强绑定的关系,由portal->createSubid变量记录关联关系。如果为1表示顶层事务,关联的是子事务。 不论是顶层事务还是子事务,提交、回滚时只会处理自己创建出来的portal。 顶层事务会清理非活跃状态的Portalÿ…...
Java、JSP企业快信系统的设计与实现
技术:Java、JSP等摘要:计算机网络的出现到现在已经经历了翻天覆地的重大改变。因特网也从最早的供科学家交流心得的简单的文本浏览器发展成为了商务和信息的中心。到了今天,互联网已经成为了大量应用的首选平台,人们已经渐渐习惯了…...
1.2(完结)C语言进阶易忘点速记
1.大端存储:高权位数字放在低地址处,低权位数字放在高地指处。(以字节为单位) 2.小端存储:低权位数字放在低地址处,高权位数字放在高地址处。(以字节为单位) 3.变量(char类型)进行运算的时候一定要注意整形提升与截断࿰…...
雅思经验(十一)
写作:WRITINGTASK 2Governments should spend money on railways rather than roads.To what extent do you agree or disagree with this statement?Give reasons for your answer and include any relevant examples from your own knowledge or experience.思路…...
C++中的智能指针
1.RAII 与引用计数了解 Objective-C/Swift 的程序员应该知道引用计数的概念。引用计数这种计数是为了防止内存泄露而产生的。 基本想法是对于动态分配的对象,进行引用计数,每当增加一次对同一个对象的引用,那么引用对象的引用计数就会增加一次…...
LSTM已死,Transformer当立(LSTM is dead. Long Live Transformers! ):下
2017 年,Google 在论文 Attention is All you need 中提出了 Transformer 模型,其使用 Self-Attention 结构取代了在 NLP 任务中常用的 RNN 网络结构。而且实验也证明Transformer 在效果上已经完败传统的 RNN 网络。Transformer 的整体模型架构如下图所示。尽管它看起来还是很…...
OJ万题详解––[NOIP2004 提高组] 合并果子(C++详解)
目录 题目 分析 参考代码 题目 题目描述 一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。 每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的…...
MySQL-字符集和比较规则
在计算机中只能存储二进制数据,那该怎么存储字符串呢?当然是建立字符与二进制数据的映射关系 了,建立这个关系最起码要搞清楚两件事: 界定清楚字符范围:需要把哪些字符映射成二进制数据?编码与解码&#x…...
微搭低代码从入门到精通12-网格布局
开发小程序首要的就是考虑布局的问题,我们在以前的版本只能选择普通容器结合图片和文本组件来构建页面。 使用通用组件布局也可以,但有个问题是你要先学习CSS,要懂布局的概念,比如需要知道啥是flex布局,然后还得熟悉每…...
【c语言】二叉树
主页:114514的代码大冒险 qq:2188956112(欢迎小伙伴呀hi✿(。◕ᴗ◕。)✿ ) Gitee:庄嘉豪 (zhuang-jiahaoxxx) - Gitee.com 引入 我们之前已经学过线性数据结构,今天我们将介绍非线性数据结构----树 树是一种非线性的…...
六、Java框架之SpringBoot
黑马课程 文章目录1. SpringBoot入门1.1 SpringBoot入门案例步骤1:创建SpringBoot项目高版本springboot常见错误步骤2:创建BookController步骤3:启动服务器并运行程序pom.xml示例1.2 官网创建SpringBoot1.3 SpringBoot工程快速启动问题导入打…...
「Python|环境安装|Windows」如何在Windows上安装Python环境?
本文主要介绍如何在Windows上安装Python,帮助初学者或者非程序员伙伴快速搭建可以运行python代码的环境。 文章目录安装python做一点小配置验证python如何安装指定版本的python编程语言的环境搭建一直是学习编程的第一道门槛。 对于如何在Linux系统上安装指定版本的…...
人工智能轨道交通行业周刊-第33期(2023.2.6-2.12)
本期关键词:高铁激光清洗、高铁确认列车、无线通信系统、推理服务优化、量子信息技术 1 整理涉及公众号名单 1.1 行业类 RT轨道交通中关村轨道交通产业服务平台人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网上榜铁路视点ITS World轨道交通联盟V…...
五分钟看懂Java字节码:极简手册
字节码新手很容易被厚厚的 JVM 书籍劝退,即使我看过相关书籍,工作真正用到时也全忘了,还得现学。 等我有了一定的字节码阅读经验,才发现字节码其实非常简单,只需要三步就能快速学会: 先了解 JVM 的基本结…...
C++ 类与对象(下)
✅<1>主页:我的代码爱吃辣 📃<2>知识讲解:C 🔥<3>创作者:我的代码爱吃辣 ☂️<4>开发环境:Visual Studio 2022 💬<5>前言:C类与对象的收尾工作&#…...
Java基础——I/O
一、异常 异常是程序中可能出现的问题,它的父类是Exception。异常分为两类,编译时异常、运行时异常。 编译时异常:没有继承RuntimeException的异常,直接继承于Exception。编译阶段就会错误提示。运行时异常:RuntimeE…...
关于@hide的理解
在上一篇文章《学习HandlerThread》我们提到虽然HandlerThread类里有getThreadHandler()方法得到Handler,但是我们不可能调用到它。因为这个方法用hide注释了 /*** return a shared {link Handler} associated with this thread* hide*/NonNullpublic Handler getT…...
使用python加密主机文件几种方法实现
本文主要介绍了使用python加密主机文件几种方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧数据加密是一种保护数据安全的技术,通过对数据进行编…...
西湖论剑 2023 比赛复现
WEB real_ez_node 在 route/index.js 中: router.post(/copy,(req,res)>{res.setHeader(Content-type,text/html;charsetutf-8)var ip req.connection.remoteAddress;console.log(ip);var obj {msg: ,}if (!ip.includes(127.0.0.1)) {obj.msg"only for…...
微信小程序更换管理员/重置管理员
方式1: 首先进入微信公众平台官网进入并登录后在管理中找到成员管理选项找到管理员点击后方的修改选项需要使用原管理员的微信进行扫码验证扫码后在手机上确认绑定新管理员,注意:如果是个人账号不可以更改成其他人。 方式2:原管…...
探索AI原生应用领域向量数据库的无限潜力
探索AI原生应用领域向量数据库的无限潜力关键词:向量数据库、AI原生应用、Embedding、向量相似度、多模态检索、大模型协同、语义理解摘要:当AI从“辅助工具”进化为“原生生产力”,一种专为AI设计的数据库——向量数据库,正在重塑…...
20个网站备份泄漏漏洞挖掘技巧!
20个网站备份泄漏漏洞挖掘技巧! 网站备份文件泄露,绝不是小问题。在网络安全攻防实战中,备份文件泄露一直被列为“高风险漏洞”,却往往被企业开发者所忽视。一次偶然的备份文件泄露,可能成为整个系统沦陷的起点。本文…...
AI 大模型落地系列|Eino 组件核心篇:ChatTemplate 为什么不是字符串拼接
声明:本文数据源于官方文档与官方实现,重点参考 ChatTemplate 使用说明。 为什么很多人学 Eino 后,写 Prompt 时还是把 ChatTemplate 用成了字符串拼接?1. ChatTemplate 是什么,不是什么2. 接口虽短,但起的…...
1949–2024年中国县级行政区划(逐年)|全国范围、75年连续、SHP格式
🔍 数据简介 本数据集完整覆盖 1949年至2024年 共 76个年份 的中国县级行政区划边界,是目前公开可获取的时间跨度最长、更新粒度最细的全国县级历史区划产品。 每一年份均提供独立、闭合、无重叠的面状矢量边界,属性表包含标准名称、行政区划…...
BERT-base-uncased完全指南:从基础原理到实战应用
BERT-base-uncased完全指南:从基础原理到实战应用 【免费下载链接】bert-base-uncased 项目地址: https://ai.gitcode.com/hf_mirrors/ai-gitcode/bert-base-uncased 一、认知铺垫:为什么BERT改变了NLP格局? 1.1 BERT的突破性意义何…...
语音转换完全上手:Retrieval-based Voice-Conversion-WebUI从入门到精通
语音转换完全上手:Retrieval-based Voice-Conversion-WebUI从入门到精通 【免费下载链接】Retrieval-based-Voice-Conversion-WebUI 语音数据小于等于10分钟也可以用来训练一个优秀的变声模型! 项目地址: https://gitcode.com/GitHub_Trending/re/Retr…...
ArcGIS Desktop许可证被占满?别慌,这3个方法帮你快速释放Advanced许可(附详细步骤)
ArcGIS Desktop高级许可被占用?3种高效解决方案与实战技巧 当你正在赶制项目报告或处理关键地理数据时,突然弹出的"All ArcGIS for Desktop Advanced licenses are in use"错误提示足以让任何GIS专业人士心跳加速。这种情况往往发生在团队共享…...
保姆级教程:在Jeecg-Vue3项目中快速集成SuperQuery高级查询组件(含完整配置代码)
Jeecg-Vue3项目实战:SuperQuery高级查询组件深度集成指南 在后台管理系统开发中,高效的数据筛选功能直接影响用户体验和操作效率。Jeecg-Vue3作为企业级快速开发框架,其内置的SuperQuery组件能够帮助开发者快速构建复杂的多条件查询面板。本文…...
Elasticsearch-03-kNN算法
Elasticsearch-03-kNN算法详解 概述 Elasticsearch提供了强大的k近邻(k-Nearest Neighbors, kNN)搜索功能,支持两种实现方式:暴力搜索和近似搜索。本文档将详细介绍这两种kNN算法的原理、优缺点和适用场景。 1. 暴力搜索ÿ…...
【MySQL | 第一篇】 深入理解三大日志(undo Redo Bin)
目录 Undo Log日志 Redo Log日志 Redo Log与Bin Log的区别 Bin Log日志 三大日志全流程 Undo Log日志 一、核心定义 Undo Log 是MySQL InnoDB存储引擎特有的事务回滚日志,核心作用是记录事务执行前的数据版本,用于事务回滚、MVCC实现,是…...
