PostgreSQL函数自动Commit/Rollback所带来的问题

一、综述

今天在PostgreSQL遇到一个奇怪的现象,简而言之,是想用函数(存储过程)实现插入记录,整个过程没报错但事后却没找到记录!忙活半天,才发现原因是PostgreSQL函数(存储过程)有自动COMMIT或ROLLBACK的特殊规定。

二、问题重现

以下用示例表和示例代码来重现该问题。

create table t1 
(ID int not null primary key,name varchar(20)
);

涉及的存储过程是从oracle那边直接拷贝过来后再修改过的,原先是动态SQL,这里简化为静态SQL。注意其中有个commit;根据PostgreSQL的要求,对事务增加begin...exception...end,否则会有错误或警告。示例脚本代码为:

复制代码

create or replace function p1(pid int, pname varchar)
returns void as $$
beginbegin             --pg对事务的要求insert into t1 values(pid, pname);commit;exception      when others thenend;              --pg对事务的要求
end;
$$ language plpgsql;

依次执行脚本创建存储过程、调用存储过程、查找示例表,结果如下: 

postgres=# \i test1.sql
CREATE FUNCTION
postgres=# select p1(1, 'abc');p1
----
(1 行记录)postgres=# select * from t1;

  id | name
  ----+------
  (0 行记录)

要插入的记录并不存在!惊喜不惊喜?意外不意外?

三、原因分析及解决

仔细查找有关资料,发现有这么一个解释:

Functions and trigger procedures are always executed within a transaction established by an outer 
query — they cannot start or commit that transaction, since there would be no context for them to 
execute in. However, a block containing an EXCEPTION clause effectively forms a subtransaction that 
can be rolled back without affecting the outer transaction.

其意义是PostgreSQL的函数总是默认为一个事务,总是自动Commit或Rollback。

其实一开始没增加begin...exception...end时,PostgreSQL报错“can't begin/end transaction  in pl/pgsql”,已经隐含了这层信息。只是脑子里还是延续Oracle的习惯,而画蛇添足了。

于是,修改存储过程的脚本,按最简单的法子来

create or replace function p2(pid int, pname varchar)
returns void as $$
begininsert into t1 values(pid, pname);
end;
$$ language plpgsql;

为验证此说法是否正确,在再次创建函数、调用函数后,增加一个回滚(事先已设置AutoCommit为false)的操作,然后再查询记录:

postgres=# \i test1.sql
CREATE FUNCTION
postgres=# select p2(1, 'abc');p2
----
(1 行记录)postgres=# rollback;
WARNING:  there is no transaction in progress
ROLLBACK
postgres=# select * from t1;id | name
----+------1 | abc
(1 行记录)

复制代码

四、总结

Oracle是可以在存储过程或函数里指定Commit/Rollback的,如果没有,则外部调用者可以回滚存储过程内部的操作。

但在PostgreSQL,函数(存储过程)总是自动将其所有操作当作一个事务,外部无法对内部操作提交或回滚。

问题好像已经解决,但留有一个疑问没弄明白,为什么PostgreSQL允许在函数体中加关于事务的begin...exception...end,但结果却好像是没提交?

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

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

相关文章

linux 进程补充

环境变量 基本概念 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数 如:我们在编写C/C代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪 里,但是照样可以链接成功&#…

Spring Boot常用注解深度解析:从入门到精通

今天,这篇文章带你将深入理解Spring Boot中30常用注解,通过代码示例和关系图,帮助你彻底掌握Spring核心注解的使用场景和内在联系。 一、启动类与核心注解 1.1 SpringBootApplication 组合注解: SpringBootApplication Confi…

前部分知识复习05

一、多级渐远贴图MipMap 选择贴图,可以勾选贴图的多级渐远效果 [IntRange]_MipMap("MipMap",Range(0,12))0 //多级渐远贴图的LOD调节滑杆 _MipMapTexture("MipMapTexture",2D)"white"{} //定义多级渐远贴图 多级渐远贴图的采样…

解锁反序列化漏洞:从原理到防护的安全指南

目录 前言 一、什么是反序列化 二、反序列化漏洞原理 三、反序列化漏洞的危害 (一)任意代码执行 (二)权限提升 (三)数据泄露与篡改 四、常见的反序列化漏洞场景 (一)PHP 反…

理解 C 与 C++ 中的 const 常量与数组大小的关系

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C语言 文章目录 💯前言💯数组大小的常量要求💯C 语言中的数组大小要求💯C 中的数组大小要求💯为什么 C 中 const 变量可以作为数组大小💯进一步的…

MAC OS安装Homebrew

文章目录 1.下载Homebrew2.完成安装3.验证安装4.更新 Homebrew作为一个包管理器,提供了一种简便的方式来安装、更新和卸载各种命令行工具和应用程序。相比于手动下载和编译源代码,或者从不同的网站下载安装包,使用Homebrew可以显著减少这些操…

深度学习系列--04.梯度下降以及其他优化器

目录 一.梯度概念 1.一元函数 2.二元函数 3.几何意义上的区别 二.梯度下降 1.原理 2.步骤 3.示例代码(Python) 4.不同类型的梯度下降 5.优缺点 三.动量优化器(Momentum) 适用场景 1.复杂地形的优化问题 2.数据具有噪声的问…

编程AI深度实战:给vim装上AI

系列文章: 编程AI深度实战:私有模型deep seek r1,必会ollama-CSDN博客 编程AI深度实战:自己的AI,必会LangChain-CSDN博客 编程AI深度实战:给vim装上AI-CSDN博客 编程AI深度实战:火的编程AI&…

2025年2月6日(anaconda cuda 学习 基本命令)

查看电脑的显卡型号是否支持CUDA的安装 https://developer.nvidia.com/zh-cn/cuda-gpus 查看可以安装的CUDA版本 https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html CUDA安装地址 https://developer.nvidia.com/cuda-toolkit-archive Anaconda下载地址 htt…

自动化构建——make/makefile

目录 背景使用推导过程如果多个文件呢?? 背景 会不会写makefile,从侧面可以说明一个人是否具有完成大型工程的能力makefile带来的好处就是——”自动化编译“,一旦写好,只需要一个make命令,整个工程完全自…

深度整理总结MySQL——SQL的执行顺序和流程

SQL的执行顺序和流程 SQL的执行顺序执行一条select语句,发生了什么呢连接器查询缓存解析SQL执行SQL预处理器优化器执行器 总结 SQL的执行顺序 这是一条标准的查询语句: 但实际上并不是从上到下去解析的,真实的执行顺序是: 我们先执行from,join来确定表之间的连接关系&#x…

R语言 | 使用 ComplexHeatmap 绘制热图,分区并给对角线分区加黑边框

目的:画热图,分区,给对角线分区添加黑色边框 建议直接看0和4。 0. 准备数据 # 安装并加载必要的包 #install.packages("ComplexHeatmap") # 如果尚未安装 library(ComplexHeatmap)# 使用 iris 数据集 #data(iris)# 选择数值列&a…

11 享元(Flyweight)模式

享元模式 1.1 分类 (对象)结构型 1.2 提出问题 做一个车管所系统,将会产生大量的车辆实体,如果每一个实例都保存自己的所有信息,将会需要大量内存,甚至导致程序崩溃。 1.3 解决方案 运用共享技术有效…

2025年Android NDK超全版本下载地址

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC 👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资源分…

【CPP】CPP经典面试题

文章目录 引言1. C 基础1.1 C 中的 const 关键字1.2 C 中的 static 关键字 2. 内存管理2.1 C 中的 new 和 delete2.2 内存泄漏 3. 面向对象编程3.1 继承和多态3.2 多重继承 4. 模板和泛型编程4.1 函数模板4.2 类模板 5. STL 和标准库5.1 容器5.2 迭代器 6. 高级特性6.1 移动语义…

安卓开发,打开PDF文件

1、把PDF文件复制到raw目录下 &#xff08;1&#xff09;新建一个Android Resource Directory (2)Resource type 改成 raw (3) 把PDF文件复制到raw目录下 2、activity_main.xml <?xml version"1.0" encoding"utf-8"?> <LinearLayoutxmlns:and…

渗透测试之文件包含漏洞 超详细的文件包含漏洞文章

目录 说明 通常分为两种类型&#xff1a; 本地文件包含 典型的攻击方式1&#xff1a; 影响&#xff1a; 典型的攻击方式2&#xff1a; 包含路径解释&#xff1a; 日志包含漏洞&#xff1a; 操作原理 包含漏洞读取文件 文件包含漏洞远程代码执行漏洞: 远程文件包含…

Git--使用教程

Git的框架讲解 Git 是一个分布式版本控制系统&#xff0c;其架构设计旨在高效地管理代码版本&#xff0c;支持分布式协作&#xff0c;并确保数据的完整性和安全性。 Git 的核心组件&#xff1a; 工作区&#xff08;Working Directory&#xff09;&#xff1a; 工作区是你在本…

Deepseek 接入Word处理对话框(隐藏密钥)

硅基流动邀请码&#xff1a;1zNe93Cp 邀请链接&#xff1a;网页链接 亲测deepseek接入word&#xff0c;自由调用对话&#xff0c;看截图有兴趣的复用代码&#xff08;当然也可以自己向deepseek提问&#xff0c;帮助你完成接入&#xff0c;但是提问逻辑不一样给出的答案是千差万…

Redis存储⑤Redis五大数据类型之 List 和 Set。

目录 1. List 列表 1.1 List 列表常见命令 1.2 阻塞版本命令 1.3 List命令总结和内部编码 1.4 List典型使用场景 1.4.1 消息队列 1.4.2 分频道的消息队列 1.4.3 微博 Timeline 2. Set 集合 2.1 Set 集合常见命令 2.2 Set 集合间命令 2.3 Set命令小结和内部编码 2.…