Postgresql源码(93)Postgresql函数内事务控制实现原理(附带Oracle对比)

news2024/11/26 10:20:31

相关
《Postgresql源码(60)事务系统总结》
《Postgresql源码(93)Postgresql函数内事务控制实现原理(附带Oracle对比)》

0 总结

Postgresql与Oracle都是扁平化处理函数内外的事务控制语句的:即函数内的commit也会直接把函数外面的语句提交掉,函数外面的commit也会把之前函数内部的语句提交掉。

区别是:Postgresql目前还不支持在事务块内,调用带有commit的函数;Oracle是支持的。
(即显示begin启动事务,调用带有commit的函数)

还有游标部分也有一些差别。

1 Postgresql函数内事务控制介绍

PATCH:8561e4840c81f7e345be2df170839846814fa004

增加了plpgsql中事务控制的功能,即实现在plpgsql内执行commit、rollback事务控制语句。

即下列场景

1.1 支持:procedure内的事务控制语句

CREATE TABLE test1 (a int, b text);

CREATE PROCEDURE transaction_test1()
LANGUAGE plpgsql
AS $$
BEGIN
    FOR i IN 0..9 LOOP
        INSERT INTO test1 (a) VALUES (i);
        IF i % 2 = 0 THEN
            COMMIT;
        ELSE
            ROLLBACK;
        END IF;
    END LOOP;
END
$$;

CALL transaction_test1();

SELECT * FROM test1;
 a | b 
---+---
 0 | 
 2 | 
 4 | 
 6 | 
 8 |

1.2 支持:匿名块内的事务控制语句

TRUNCATE test1;

DO
LANGUAGE plpgsql
$$
BEGIN
    FOR i IN 0..9 LOOP
        INSERT INTO test1 (a) VALUES (i);
        IF i % 2 = 0 THEN
            COMMIT;
        ELSE
            ROLLBACK;
        END IF;
    END LOOP;
END
$$;

SELECT * FROM test1;
 a | b 
---+---
 0 | 
 2 | 
 4 | 
 6 | 
 8 |

1.3 不支持:事务块内调用【带事务控制的procedure】

START TRANSACTION;
CALL transaction_test1();

ERROR:  invalid transaction termination
CONTEXT:  PL/pgSQL function transaction_test1() line 6 at COMMIT

COMMIT;

1.4 不支持:事务块内调用【带事务控制的匿名块】

START TRANSACTION;
DO LANGUAGE plpgsql $$ BEGIN COMMIT; END $$;

ERROR:  invalid transaction termination
CONTEXT:  PL/pgSQL function inline_code_block line 1 at COMMIT

COMMIT;

1.5 不支持:函数内的事务控制语句

CREATE FUNCTION transaction_test2() RETURNS int
LANGUAGE plpgsql
AS $$
BEGIN
    FOR i IN 0..9 LOOP
        INSERT INTO test1 (a) VALUES (i);
        IF i % 2 = 0 THEN
            COMMIT;
        ELSE
            ROLLBACK;
        END IF;
    END LOOP;
    RETURN 1;
END
$$;

SELECT transaction_test2();

ERROR:  invalid transaction termination
CONTEXT:  PL/pgSQL function transaction_test2() line 6 at COMMIT

SELECT * FROM test1;
 a | b 
---+---

1.6 不支持:函数内调用【带事务控制的procedure】

CREATE FUNCTION transaction_test3() RETURNS int
LANGUAGE plpgsql
AS $$
BEGIN
    CALL transaction_test1();
    RETURN 1;
END;
$$;
SELECT transaction_test3();
ERROR:  invalid transaction termination
CONTEXT:  PL/pgSQL function transaction_test1() line 6 at COMMIT
SQL statement "CALL transaction_test1()"
PL/pgSQL function transaction_test3() line 3 at SQL statement
SELECT * FROM test1;
 a | b 
---+---
(0 rows)

1.7 不支持:函数内调用【带事务控制的匿名块】

CREATE FUNCTION transaction_test4() RETURNS int
LANGUAGE plpgsql
AS $$
BEGIN
    EXECUTE 'DO LANGUAGE plpgsql $x$ BEGIN COMMIT; END $x$';
    RETURN 1;
END;
$$;

SELECT transaction_test4();

ERROR:  invalid transaction termination
CONTEXT:  PL/pgSQL function inline_code_block line 1 at COMMIT
SQL statement "DO LANGUAGE plpgsql $x$ BEGIN COMMIT; END $x$"
PL/pgSQL function transaction_test4() line 3 at EXECUTE

2 Oracle行为分析

2.1 procedure内的rollback会影响外面的SQL吗?:会

测试

set autocommit off;
commit;

drop table test1;
create table test1(a int);

CREATE OR REPLACE PROCEDURE transaction_test2 (x int) AS
BEGIN
    INSERT INTO test1 (a) VALUES (1);
    INSERT INTO test1 (a) VALUES (2);
    rollback;
    INSERT INTO test1 (a) VALUES (3);
    INSERT INTO test1 (a) VALUES (4);
    commit;
    INSERT INTO test1 (a) VALUES (5);
    INSERT INTO test1 (a) VALUES (6);
    rollback;
END;
/


commit;
INSERT INTO test1 (a) VALUES (100);
INSERT INTO test1 (a) VALUES (200);
select * from test1;
call transaction_test2(0);
select * from test1;
commit;
select * from test1;

结果

SYS@orcl11g>select * from test1;

         A
----------
         3
         4

2.2 procedure内的commit会影响外面的SQL吗?:会

测试

set autocommit off;
commit;

drop table test1;
create table test1(a int);

CREATE OR REPLACE PROCEDURE transaction_test2 (x int) AS
BEGIN
    INSERT INTO test1 (a) VALUES (1);
    INSERT INTO test1 (a) VALUES (2);
    commit;
END;
/


commit;

INSERT INTO test1 (a) VALUES (100);
INSERT INTO test1 (a) VALUES (200);
select * from test1;
call transaction_test2(0);
select * from test1;
rollback;
select * from test1;

结果

SYS@orcl11g>rollback;

Rollback complete.

SYS@orcl11g>select * from test1;

         A
----------
       100
       200
         1

2.3 procedure外的rollback会影响里面的SQL吗?:会

测试

set autocommit off;
commit;

drop table test1;
create table test1(a int);

CREATE OR REPLACE PROCEDURE transaction_test2 (x int) AS
BEGIN
    INSERT INTO test1 (a) VALUES (1);
    INSERT INTO test1 (a) VALUES (2);
END;
/


commit;

INSERT INTO test1 (a) VALUES (100);
INSERT INTO test1 (a) VALUES (200);
select * from test1;
call transaction_test2(0);
select * from test1;
rollback;
select * from test1;

结果

SYS@orcl11g>select * from test1;

no rows selected

2.4 procedure外的commit会影响里面的SQL吗?:会

.

2.5 procedure外的savepoint

正常的savepoint是在事务内部使用的,例如:

UPDATE employees 
    SET salary = 7000 
    WHERE last_name = 'Banda';
SAVEPOINT banda_sal;

UPDATE employees 
    SET salary = 12000 
    WHERE last_name = 'Greene';
SAVEPOINT greene_sal;

SELECT SUM(salary) FROM employees;

ROLLBACK TO SAVEPOINT banda_sal;
 
UPDATE employees 
    SET salary = 11000 
    WHERE last_name = 'Greene';
 
COMMIT; 

如果在事务内调用过程,过程中的事务控制语句会直接结束掉当前事务。

commit;
INSERT INTO test1 (a) VALUES (100);
INSERT INTO test1 (a) VALUES (200);
savepoint sp1;
select * from test1;

call transaction_test2(0);   -- 调用这个函数的效果和执行rollback的效果是完全一样的,都会结束掉当前事务

rollback to savepoint sp1;

ERROR at line 1:
ORA-01086: savepoint 'SP1' never established in this session or is invalid

call 过程导致当前事务结束,检查点自动释放。效果和直接执行commit/rollback相同。

2 Postgresql实现函数内事务控制的源码分析

PATCH在函数调用的入口增加了atomic变量

ExecuteCallStmt(ParseState *pstate, CallStmt *stmt, bool atomic)

atomic含义?

为true表示PL内不能出现事务控制语句,否则报错。即函数、或事务块内的场景为true;过程为false。

atomic如何确定?

atomic的确定受几个函数影响,且function、procedure进入堆栈不同,总结如下:
在这里插入图片描述

具体调用场景中,关键变量的值:

standard_ProcessUtility函数中contextstandard_ProcessUtility函数中IsTransactionBlock()plpgsql_call_handler函数中fcinfo->contextplpgsql_call_handler函数中CallContext->atomic
【成功】call procedurePROCESS_UTILITY_TOPLEVELfalseT_CallContextfalse
【失败】select function不走不走nullnull
【失败】事务块内call procedurePROCESS_UTILITY_TOPLEVELtrueT_CallContexttrue
【成功】匿名块内call procedurePROCESS_UTILITY_QUERY_NONATOMICfalseT_CallContextfalse
【失败】事务块内匿名块内call procedurePROCESS_UTILITY_QUERY_NONATOMICtrueT_CallContexttrue
【失败】匿名块内select function不走不走nullnull

*对于function来说,进入plpgsql_call_handler后fcinfo->context为空,没有后续判断。

3 怎样支持1.3?

注意事务块的状态:

  • 单条SQL的事务状态是TBLOCK_STARTED,CommitTransaction可以直接提交。
  • 事务块的的SQL的事务状态是TBLOCK_INPROGRESS,CommitTransaction不能直接提交。

不能仅仅使用状态机函数CommitTransaction,需要加上commit或rollback的底层处理函数。

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

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

相关文章

aws eks 节点驱逐和OOMkill

资料 解决 K8s 调度不均衡问题kubernetes pod内容器状态OOMKilled和退出码137全流程解析 集群中pod触发oom的原因 默认pod能够使用节点的全部可用资源。节点的可分配资源如下 Allocatable Node Capacity - (kube-reserved) - (system-res…

Linux基本指令(2)

Linux基本指令(2) 📟作者主页:慢热的陕西人 🌴专栏链接:Linux 📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言 本博客将展示25-30个LInux中常用的命令,…

计算机网络第9章 无线网络和移动网络

目录 9.1 无线局域网 WLAN 9.1.1 无线局域网的组成 1. 无线局域网 WLAN (Wireless Local Area Network) 2. IEEE 802.11 3. 移动自组网络 9.1.2 802.11 局域网的物理层 9.1.3 802.11 局域网的 MAC 层协议 1. CSMA/CA 协议 2. 时间间隔 DIFS 的重要性 3. MAC两个子层…

fpga实操训练(按键消抖)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 之前我们谈到按键输入,其中涉及的功能就是,当按键按下的时候,led灯亮起来。等到按键弹起来的时候,l…

NLP领域表达退化各向异性理解及对应策略总结

前言:今年8月份在与同学撰写deepfake相关论文的过程中偶然听导师提到各向同性与各向异性这两个词,当时以为这是cv领域的概念,回去一查发现是物理领域的,就没再深究。最近看到一篇使用对比学习解决开放式长文本生成中模型退化问题的…

在 Spring Boot 中使用 HikariCP 连接池

目前星标 12K,被使用次数更是达到了 43.1K。再来看看它的自我介绍。 牛逼的不能行啊,原来 Hikari 来源于日语,“光”的意思,这意味着快得像光速一样吗?讲真,看简介的感觉就好像在和我的女神“汤唯”握手一样…

基于SSM的企业管理系统

项目描述 临近学期结束,还是毕业设计,你还在做java程序网络编程,期末作业,老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下,你想解决的问…

[ vulhub漏洞复现篇 ] GhostScript 沙箱绕过(任意命令执行)漏洞CVE-2019-6116

🍬 博主介绍 👨‍🎓 博主介绍:大家好,我是 _PowerShell ,很高兴认识大家~ ✨主攻领域:【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 🎉点赞➕评论➕收藏 养成习…

软件测试面试必看,资深测试工程师面试题集锦 全网首发

全网首发,最牛的全套软件测试 ,自动化测试面试题,这些面试题都在文章末尾,有需要的可以自取 废话少说直接开始咱们今天的整体内容, 1.自我介绍? 我是谁、工作几年、你上家公司做什么、负责什么、你的优势…

史上最全事件相机DVS/Event-based Camera的介绍和分析综述文章

史上最全事件相机DVS/Event-based Camera的介绍和分析1. DVS 的一些介绍2. 基于事件的视觉传感器发展现状与趋势3. 事件相机的动态范围:信噪比动态范围DR结论4. 新型相机DVS/Event-based camera的发展及应用应用点传统相机的缺点事件相机的优点5. 事件相机在无人驾驶…

[技巧]还在使用RDP远程windows?OpenSSH远程win10操作系统!

文章目录前言一、Win10开启OpenSSH服务1.1 查看本机是否安装了openssh1.2 下载openssh1.3 查看ssh是否安装1.4 安装openssh服务端1.5 启动openssh服务1.6 查看openssh服务是否启动正常二、开始远程2.1 在目标机器上查看用户名2.2 使用ssh命令远程三、常见问题3.1 ssh命令登陆提…

C# 接口

一 接口 接口(interface)实际上是一个约定。 如:ICloneable,IComparable; 接口是抽象成员的集合; ICIonable含有方法clone(); IComparable含有方法compare(); 接口是一个引用类型,比抽象类更抽象。 帮助实现多重继承…

配置本地Git从Gitlab上拉取项目

配置本地Git从Gitlab上拉取项目 安装git: https://git-scm.com/downloads git官网下载安装包,安装时一路next即可 ①配置用户名,邮箱 创建一个文件夹,任意位置即可鼠标右键选择,git bash here配置提交人姓名、邮箱 g…

一起学习用Verilog在FPGA上实现CNN----(二)卷积层设计

1 打开Vivado工程 Vivado工程文件如图: 打开Vivado软件,打开工程,如图: 自动升级到当前版本,如图: 暂时选择现有开发板的型号,如图: 出现一条警告性信息,暂时先不管&…

2023年第五届人工智能与机器学习国际会议(FAIML 2023)

2023年第五届人工智能与机器学习国际会议(FAIML 2023) 重要信息 会议网址:www.faiml.org 会议时间:2023年4月14-16日 召开地点:中国北京 截稿时间:2023年3月15日 录用通知:投稿后2周内 收录检索:EI,S…

差分进化算法在图像处理中的应用研究(Matlab代码实现)

目录 💥1 概述 📚2 运行结果 🎉3 参考文献 👨‍💻4 Matlab代码 💥1 概述 本文为Storn和Price制定的著名差分进化计算智能算法的实现。该算法使用Otsu准则作为适应度函数,可用于使用多个阈值…

为什么球的表面积不能用周长积分而体积可以用面积积分?

问题描述: 将面积从最底下一层层叠到最上面可以得到球体积的正确公式 但是将周长从最底下一层层叠到最上面会得到错误结果,错误结果的几何意义是什么?以及是在什么地方积错了? 解答一: 首先, ∫−RR2πR2…

计算机研究生就业方向之去央企(国企)信息化部门

我一直跟学生们说你考计算机的研究生之前一定要想好你想干什么,如果你只是转码,那么你不一定要考研,至少以下几个职位研究生是没有啥优势的: 1,软件测试工程师(培训一下就行) 2,前…

C语言:星期一问题

题目需求 整个20世纪(1901年1月1日至2000年12月31日之间),一共有多少个星期一? (不要告诉我你不知道今天是星期几哈) 请用一段程序实现了这一功能。 算法思路 判断1901年1月1日到2000年12月31的每一天是星期几,如果是星…

前端开发:JS中关于正则表达式的使用汇总

前言 在前端开发过程中,关于正则表达式的使用也是必备技能,尤其是在实际业务需求的时候,需要处理一些不能按照正常语句操作的逻辑,如前端开发中的字符匹配、参数处理等都需要正则表达式来匹配截取处理。虽然正则表达式在程序开发中…