PostgreSql和Oracle的事务机制区别以及对程序的影响

news/2024/7/9 23:01:16 标签: postgresql, oracle, 数据库

前言

几年前IT信息产业的一些核心技术包括架构、产品以及生态都是国外制定,然而自从“遥遥领先”公司被制裁后,国家开始大力支持信息产业“新基建”,自2020年开始市场上涌现出了大量的国产化软件,就国产化数据库而言我所在的公司有两款国产化数据库,一款是基于mysql,另一款则是基于postgreSQL,相信市面上大多国产化数据库也是基于这两款开源数据库演化而来。一般使用国产化数据库的项目大多是一些政企项目或者公司自己的核心项目,这些项目原先也大多使用的是oracle数据库,那么今天就来聊聊把项目从oracle迁移到基于PostgreSql的国产化数据库(下文将直接使用postgreSql替代基于postgresql的国产化数据库)上遇到的一个问题。

一、系统事务管理

事务管理是任何系统都应该具备的核心功能,然而一些java开发者包括我在内在写代码时往往会忽略这个重要的东西,这并不是我不了解事务管理的重要性,其最大的原因就是日常使用的框架都提供了很完善的事务管理机制,不需要开发者针对事务上写大量代码,比如spring,spring提供的事务管理有两种一种是声明式,另一种是编程式,目前我个人使用最多的就是声明式事务了。然而声明式事务我个人认为有个缺点,就是事务控制的粒度太大,因为声明式事务时基于注解实现的,所以最小粒度为方法级别。

二、问题的暴露

工作中维护老代码时,发现祖传写法都是下图这个样子,在service类上添加事务注解,方法上和方法调用的子方法并不做事务控制,这个例子中AutomaticRechargeInitiationProcess类中还是很多逻辑,换句话说这个程序中只要出现了一点问题,那么事务就要全部进行回滚。
在这里插入图片描述
于是代码维护者们发现有些程序即使错误了也不应该进行回滚,比如记录一些程序处理过程等或者错误是在预料之中的。于是又在AutomaticRechargeInitiationProcess代码中添加了类似下图的代码。

在这里插入图片描述
类似这种代码其实在一些大型老旧项目中是很常见的,原因是项目迭代时间太久,经手的开发人员技术水平参差不齐,比如我目前维护的项目截至2024年一月已经整整12个年头了,经手的开发人员没有一百也有八十了,代码的规范性已经被破坏,代码的维护变得困难。而另一种情况是,随着时间的发展,业务也在演进,比如从2020年新增了一种业务,需要新增表,正确的做法是程序中根据时间节点判断是否查询新表,然而总有大聪明不按套路出牌,他的逆向思维促使他程序中不做任何判断,反而新建了若干张历史月份表。后续开发者可能发现了隐患,于是在程序中使用try catch的方式将查询新表的代码进行处理。这样看似完美,实际运行倒也未发生什么问题。

问题的暴露发生在了今年的国产化替代项目上,项目在功能测试阶段由于都是使用的近几月的数据进行的自动化回归验证,所以并没有发现问题,当上到生产上时,发现业务在查询比较久远的历史数据时,前台直接报错了,查看日志发现报错几乎全部为“current transaction is aborted, commands ignored until end of transaction block”,根据日志可以发现是数据库驱动抛出的异常,日志还打了某张表不存在。异常如下:

在这里插入图片描述
既然找到了日志那问题的定位也就简单了,原因就是因为表不存在触发了postgreSql的事务机制,导致了继续使用出现过异常的事务进行数据库操作就会报出上图异常,那么问题来了,原来的oracle为什么不会出现问题?

PostgreSql和Oracle的事务机制区别

咨询了公司大佬,给出的答复是:Oracle具有子事务功能,Oracle没有遵循SQL规范,只做了部分回滚;postgreSql遵循SQL规范,一个事务的多条SQL要么全部成功要么全部失败。

自己查询了资料发现:

orale的子事务是指一个大事务可以包含多个小事务,而每个小事务可以单独提交或者回滚,同时也支持跟随父事务进行提交或回滚。其实现原理为嵌套事务结合保存点来实现的。

postgresql也支持“子事务”,但是pg的子事务和oracle不同,他不具备独独立提交和回滚的能力,必须依赖大事务,但是这个功能也需要在jdbc连接串中配置autosave=always&cleanupSavepoints=true来开启。但是这种方式存在风险,如果一个事务中存在多个DML语句,这样失败的回滚,成功的提交,会造成业务数据不一致,使用时需要谨慎。
官方对两个参数的解释如下:
在这里插入图片描述
以上便是我在去O实践中遇到的一个问题。


http://www.niftyadmin.cn/n/5351823.html

相关文章

Execution failed for task ‘:app:compileFlutterBuildDebug‘. 解决

前言 项目场景:在Flutter项目中 或 在嵌入Flutter模块的Android原生项目; 启动场景:在Android原生端 编译 或 运行 项目时,可能出现这个异常; 异常 Build窗口并没有追踪到,引发异常代码位置,…

总结NB-IoT模块和单片机的区别

在学习了NB-IoT模块后,紧接着又学习了单片机系统,单片机和NB-IoT模块有什么不同之处呢,总结为以下几点。 大纲如图: 一、硬件层面 1、采用芯片不同, (1)封装:封装尺寸、方式不同&a…

【极数系列】Flink环境搭建Docker版本(04)

文章目录 引言01 Linux安装Docker1.安装yum-utils软件包2.安装docker3.启动docker4.设置docker自启动5.配置Docker使用systemd作为默认Cgroup驱动6.重启docker 02 docker部署Flink1.18版本1.拉取最新镜像2.检查镜像3.编写dockerFile文件4.执行dockerFile5.检查flink是否启动成功…

Apache Paimon基础记录

基本都是在官网的学习,简单记录一下其中的核心特点 Apache Paimon 官网 Apache Paimon | Apache Paimon 根据官网介绍去快速了解 paimon 是用来设计做什么,可以做什么,对比与其他数据湖有什么特点,如何使用 Paimon 特点 前身…

Modelarts零代码体验,一键实现工地钢筋盘点,建筑提效新思维

前言 最近家附近的好几块地,同时在进行房产开发建设,早晚都能看到建筑师傅们在忙碌。 某天,夜跑中,发现前方的建筑工地,师傅们忙活的热火朝天,塔吊也在吊运钢筋中。 准备绕路的时候,旁边负责…

exits和in在ORALCE数据库中那个执行效率更高

以下是Oracle中EXISTS和IN的例子: EXISTS的例子: SELECT column1, column2 FROM table1 WHERE EXISTS ( SELECT 1 FROM table2 WHERE table1.id table2.id ); 上述查询会返回table1中所有与table2有匹配记录的行。EXISTS子查…

OkHttp的理解和使用

OkHttp是一个流行的开源HTTP客户端库,用于在Android和Java应用程序中进行网络请求。它提供了简洁易用的API和丰富的功能,包括同步和异步请求、文件上传和下载、缓存管理等。 下面是一个详细的OkHttp教程,帮助你理解和使用OkHttp:…

【UE 材质】闪烁的星星材质

效果 步骤 1. 新建一个材质这里命名为“M_Flare” 打开“M_Flare”,设置混合模式为半透明,着色模型为无光照,勾选双面 按住U鼠标左键来快速添加一个纹理坐标节点 继续添加如下节点 此时预览效果如下 如果希望有一点动画效果还需添加如下节点…