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 $$
begin
  begin             --pg对事务的要求
  insert into t1 values(pid, pname);
  commit;
  exception      
  when others then
  end;              --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 $$
begin
  insert 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,但结果却好像是没提交?

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Ollama+deepseek+Docker+Open WebUI实现与AI聊天

1、下载并安装Ollama 官方网址:Ollama 安装好后,在命令行输入, ollama --version 返回以下信息,则表明安装成功, 2、 下载AI大模型 这里以deepseek-r1:1.5b模型为例, 在命令行中,执行&…

Immutable设计 SimpleDateFormat DateTimeFormatter

专栏系列文章地址:https://blog.csdn.net/qq_26437925/article/details/145290162 本文目标: 理解不可变设计模式,时间format有线程安全要求的注意使用DateTimeFormatter 目录 ImmutableSimpleDateFormat 非线程安全可以synchronized解决&a…

基于Hexo实现一个静态的博客网站

原文首发:https://blog.liuzijian.com/post/8iu7g5e3r6y.html 目录 引言1.初始化Hexo2.整合主题Fluid3.部署评论系统Waline4.采用Nginx部署 引言 Hexo是中国台湾开发者Charlie在2012年创建的一个开源项目,旨在提供一个简单、快速且易于扩展的静态博客生…

Diskgenius系统迁移之后无法使用USB启动

前言 本文用于记录系统迁移中遇到的问题及解决方法,如有不对请指出,谢谢! 现象 使用DiskGenius进行系统迁移后,使用USB启动失败,反复在品牌logo和黑屏之间切换,期间还会在左上角显示”reset system“报错…

数据库系统概论的第六版与第五版的区别,附pdf

我用夸克网盘分享了「数据库系统概论第五六版资源」,点击链接即可保存。 链接:https://pan.quark.cn/s/21a278378dee 第6版教材修订的主要内容 为了保持科学性、先进性和实用性,在第5版教材基础上对全书内容进行了修改、更新和充实。 在科…

简单说一下CAP理论和Base理论

CAP理论 什么是CAP 一致性 可用性 分区容错性:系统如果不能再时限内达成数据一致性,就说明发生了分区的情况 然后当前操作在C和A之间做出选择 例如我的网络出现问题了,但是我们的系统不能因为网络问题就直接崩溃 只要我们的分布式系统没…

网络工程师 (22)网络协议

前言 网络协议是计算机网络中进行数据交换而建立的规则、标准或约定的集合,它规定了通信时信息必须采用的格式和这些格式的意义。 一、基本要素 语法:规定信息格式,包括数据及控制信息的格式、编码及信号电平等。这是协议的基础,确…

Linux网络 | 理解NATPT, 数据链路层Done

前言:本节内容结束数据链路层, 本节的重要内容有两个:一个是见一个综合性面试题,另一个就是NAT技术NATPT。 那么废话不多说, 开始我们的学习吧!!! ps:最好先看一下上一篇…

Linux/C高级(精讲)----shell结构语句、shell数组

shell脚本 功能性语句 test 可测试对象三种:字符串 整数 文件属性 每种测试对象都有若干测试操作符 1)字符串的测试: s1 s2 测试两个字符串的内容是否完全一样 s1 ! s2 测试两个字符串的内容是否有差异 -z s1 测试s1 字符串的长度是…

DeepSeek本地部署并提供远程连接(小白教程)

文章目录 一、DeepSeek介绍二、为什么要本地部署三、本地部署教程1.安装Ollama2.下载部署DeepSeek模型3.安装Chatbox可视化工具4.非局域网远程连接 四、DeepSeek官方开放平台API对接 参考资料:DeepSeek本地搭建部署详细图文教程 - 搬主题 一、DeepSeek介绍 DeepSeek…

足球俱乐部管理系统的设计与实现

🍅点赞收藏关注 → 添加文档最下方联系方式咨询本源代码、数据库🍅 本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目希望你能有所收获,少走一些弯路。🍅关注我不迷路🍅 项目视频 足…

Star300+ 开源项目Developer-RoadMap 计算机各领域学习路线图集大成者

一、开发者的“成长宝典”来了 你是否在编程的海洋中迷茫,不知该驶向何方?你是否渴望一份清晰的指南,引领你在开发者的道路上稳步前行?今天,就为大家带来一份堪称“成长宝典”的开源项目: https://github.com/kamran…

链表和 list

一、单链表的模拟实现 1.实现方式 链表的实现方式分为动态实现和静态实现两种。 动态实现是通过 new 申请结点,然后通过 delete 释放结点的形式构造链表。这种实现方式最能体 现链表的特性; 静态实现是利用两个数组配合来模拟链表。一个表示数据域&am…

C语言switch case语句详解(非常详细)

在C语言中,switch case 语句是一种多分支选择结构,用于根据变量的值执行不同的代码块。 相比于if else语句,switch case在处理多个固定值的条件判断时更加简洁和高效。本文将详细讲解switch case语句的用法、语法格式、实例代码、注意事项&a…

DeepSeek本地部署

前言 蛇年过年前,国产大模型 DeepSeek以更高的效率、更低的计算成本火爆国内外,成为现象级AI,但由于访问人数过多经常频繁出现反应迟缓甚至是宕机的情况。 但万幸的是,DeepSeek 是一个开源模型,我们可以通过本地部署…

springboot简单应用

快速开发Springboot项目实现简单的增删改查,前期需要准备:idea与postman安装 Maven,MySQL(8),JDK(21) 目录 前言 springboot 使用3.0版本,JDK使用21,MySQL使用8版本 开发环境IDEA使用2024版本 …

tomcat核心组件及原理概述

目录 1. tomcat概述 1.1 概念 1.2 官网地址 2. 基本使用 2.1下载 3. 整体架构 3.1 核心组件 3.2 从web.xml配置和模块对应角度 3.3 如何处理请求 4. 配置JVM参数 5. 附录 1. tomcat概述 1.1 概念 什么是tomcat Tomcat是一个开源、免费、轻量级的Web服务器。 Tomca…

【Linux】24.进程间通信(3)

文章目录 3.6 systemv共享内存3.6.1 共享内存函数3.6.3 一个简单的共享内存代码实现3.6.4 一个复杂的共享内存代码实现3.6.4 key和shmid的主要区别: 3.7 systemv消息队列(了解)3.8 systemv信号量(了解)进程互斥四个问题理解信号量…

115,【7】 攻防世界 web fileinclude

进入靶场 试着访问了几个文件&#xff0c;都没得到信息&#xff0c;f12看看源码 还真有 <?php // 检查是否开启了错误显示功能 // ini_get 函数用于获取 PHP 配置选项的值&#xff0c;这里检查 display_errors 选项是否开启 if( !ini_get(display_errors) ) {// 如果错误…

深入理解Java引用传递

先看一段代码&#xff1a; public static void add(String a) {a "new";System.out.println("add: " a); // 输出内容&#xff1a;add: new}public static void main(String[] args) {String a null;add(a);System.out.println("main: " a);…