挖掘PostgreSQL事务的“中间态”----更加严谨的数据一致性?

1.问题

今天在上班途中,中心的妹纸突然找我,非常温柔的找我帮忙看个数据库的报错。当然以我的性格,妹子找我的事情对我来说优先级肯定是最高的,所以立马放下手中的“小事”,转身向妹子走去。具体是一个什么样的问题呢?

可以看到,这是一个postgreSQL的问题,妹子通过python的pscopg2包,通过executemany()的方法,对PostgreSQL数据库进行多条数据的写入操作,但是报了以下错误

psycopg2.errors.InFailedSqlTransaction: current transaction is aborted, commands ignored until end of transaction block 

2.问题分析

对这个问题乍看一眼,其实就是当前的事务被中断了,但是具体什么原因,这里并没有告诉我们,所以第一想法,这会不会是触发了什么bug,导致事务突发中断。但是为了解决妹子多条数据插入这个事情,我们还是得确定它问题到底是不是bug。于是,我们还是得先到数据库上看看这个事务的相关日志。

通过对日志的检查,我们看到了以下操作过程:

2023-11-15 15:29:53.682 CST [52096] STATEMENT:  data = [
            (202311,cpu,18%,,),
            (202311,men,50%,test,),
            (202311,storage,3%,,)
        ]
        sql = "insert into aa (a,b,c,d) value (%s,%s,%s,%s)"
        select * from fk ;
2023-11-15 15:33:52.180 CST [54538] ERROR:  syntax error at or near "value" at character 40
2023-11-15 15:33:52.180 CST [54538] STATEMENT:  insert into aa (a,b,c,d) value ('202311','cpu','18%','')
2023-11-15 15:34:06.611 CST [54538] ERROR:  current transaction is aborted, commands ignored until end of transaction block

从数据库层查看,可以看出,程序通过data定义一个列表,列表中包含了三组数据,并通过insert的sql插入数据库,但是当我们执行到第一个sql时,由于语法错误(insert into … values …的values写成了value),导致插入语句失败,然后报出了我们看到的事务中断的错误。
嗨,看到这里,松了口气,其实就是语法写错导致事务中断而已,不是什么bug嘛,既然事务失败了,那么我们重新发起操作即可。可是妹子又跟我说,后续她改正了错误,然后执行,可还是会报这个错误。

这时,我突然想起在很久之前做过的一些关于pg事务的测试,当时突然测试出一个奇怪的现象,就是当我手动启用一个事务的时候,如果这个事务中的sql执行出错,那么我接着改正sql,继续执行还是会报错,只有当我做了rollback或者commit之后,才能够在这个会话中继续执行sql。

而妹子遇见的这个现象好像和这个确实很像,为了进一步验证想法,我做了之前的实验,过程很简单:

begin;
BEGIN
insert into fk value(now(),'1','2','3');
ERROR:  syntax error at or near "value"
LINE 1: insert into fk value(now(),'1','2','3');
                       ^
insert into fk values(now(),'1','2','3');
ERROR:  current transaction is aborted, commands ignored until end of transaction block
insert into fk values(now(),'3','2','3');
ERROR:  current transaction is aborted, commands ignored until end of transaction block
insert into fk values(now(),'3','2','');
ERROR:  current transaction is aborted, commands ignored until end of transaction block
select * from fk;
ERROR:  current transaction is aborted, commands ignored until end of transaction block

很容易的,我们模拟出了这个问题,这个时候我们去看当前的活动会话:

postgres=# select pid,usename,application_name,wait_event_type,wait_event,state,query from pg_stat_activity where wait_event_type='Client';

  pid  | usename  | application_name | wait_event_type | wait_event |             state             |       query       
-------+----------+------------------+-----------------+------------+-------------------------------+-------------------
 19137 | postgres | psql             | Client          | ClientRead | idle in transaction (aborted) | select * from aa;
(1 row)

此时,我们通过rollback,结束这个事务:

rollback;
ROLLBACK

再次查看当前活动会话:

postgres=# select pid,usename,application_name,wait_event_type,wait_event,state,query from pg_stat_activity where wait_event_type='Client';
  pid  | usename  | application_name | wait_event_type | wait_event | state |   query   
-------+----------+------------------+-----------------+------------+-------+-----------
 19137 | postgres | psql             | Client          | ClientRead | idle  | rollback;

--插入数据测试:
insert into aa values(now(),'1','2','3');
INSERT 0 1

--查询表测试:
select * from aa;
...

注:我们知道,在postgresql中,通过psql登陆,事务默认是自动提交的,因此我们不需要在dml操作后,执行commit或者rollback操作,想要关闭事务的自动提交,则有两个方法:

1.通过begin指定开始一个事务块;
2.通过设置AUTOCOMMIT的方式关闭自动提交

postgres=# \set AUTOCOMMIT off
postgres=# \echo :AUTOCOMMIT
off

那么上面的现象就很好理解了,我通过begin的方式,开启了一个事务块,在这个事务块中,我执行了一个错误的sql,导致这个事务出现问题中断,而这个事务则进入了一个“中间态”,而会话则是一个idle in transaction (aborted)的状态,此时,只要在这个会话中不论我们执行什么sql,都会报错。而当我做了rollback后,则结束了这个事务,同时会话也成为了idle状态。而我们再次做其他操作时,则是进入了新的事务,并自动提交。

那么,妹子的事情也能解释的通了,通过python等客户端对数据库进行连接操作,默认是开启了一个事务块。妹子在写测试sql的时候,发现了错误并及时修正,但是并未做回滚或提交,结束事务。此时,事务处于“中间态”,会话处于abort。

3.源码证实

虽然妹子的问题解决了,但是实际是不是这样呢?这只能在源码中看看了。在源码中,我找到这么一段代码及描述:
在这里插入图片描述

大概意思就是说,当我们在一个事务块中,由于语句造成的中断,虽然我们什么都没做成,但是它还会保持中断状态,直到我们收到一个rollback命令;而当我们从用户客户端收到了rollback命令,那么我们就会讲已经abort的回话清理并恢复到空闲状态。

4.总结

从这个问题中,我们可以看到,PostgreSQL在进行事务操作时候,为了保证事务的一致性,会有一个事务的“中间态”,这里我打个比方,即这个“中间态”保证了PostgreSQL同一个事务中的操作“一荣俱荣,一损俱损”。即在一个事务中,我们可能会存在多个dml操作,而当其中的一个操作失败后,整个事务中的操作都会失败,并且需要手动回滚,而不会存在部分成功部分失败。

对比oracle/mysql,当我们在一个事务中,执行多个dml操作时,正确的操作则会成功(这里会写入到buffer中,旧数据则会在undo中),错误的操作则会失败,从而形成了部分成功的情况。

这样看来,好像PostgreSQL的事务对于整个业务的一致性要更加严谨。比如A给B转钱,那么A的账户要减掉10000,B的账户要增加10000。我们可以将这个过程分为两个update操作,如果按照Oracle/Mysql数据库层面的处理逻辑,但当某些原因,B账户增加10000的update执行失败,此时如果我们做了commit操作,那么则只有A的账户被被更新,B的账户则不变,此时业务则出现了错误。但是如果以PostgreSQL的“中间态”理解,此时A、B的账户则都会回退,看起来更加合理。

当然,这只是我的一些理解,也欢迎各位大佬可以一起交流,指正错误。

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

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

相关文章

这才是 SpringBoot 统一登录鉴权、异常处理、数据格式的正确打开姿势

本篇将要学习 Spring Boot 统一功能处理模块,这也是 AOP 的实战环节 用户登录权限的校验实现接口 HandlerInterceptor WebMvcConfigurer 异常处理使用注解 RestControllerAdvice ExceptionHandler 数据格式返回使用注解 ControllerAdvice 并且实现接口 Response…

阿尔法狗的算法解析-增强学习和蒙特卡洛树搜索算法

阿尔法狗(AlphaGo)是谷歌旗下DeepMind开发的一个著名的增强学习算法,它在围棋领域取得了显著的成就。本文主要探讨其中两个重要的算法:增强学习算法和蒙特卡洛树搜索算法。 AlphaGo涉及的算法 AlphaGo是DeepMind团队开发的一个由多种算法和技术组合而成的系统,其包括以下…

【Linux网络】典型NAS存储方式:NFS网络共享存储服务

一、关于存储的分类 二、NFS的介绍 nfs的相关介绍: 1、原理 2、nfs的特点 3、nfs软件学习 4、共享配置文件的书写格式 关于权限,学习: 5、关于命令的学习: 三、实验操作 1、nfs默认共享权限(服务端设置&#…

大数据-之LibrA数据库系统告警处理(ALM-12049 网络读吞吐率超过阈值)

告警解释 系统每30秒周期性检测网络读吞吐率,并把实际吞吐率和阈值(系统默认阈值80%)进行比较,当检测到网络读吞吐率连续多次(默认值为5)超过阈值时产生该告警。 用户可通过“系统设置 > 阈值配置 >…

【数据结构】C语言实现栈

🎈个人主页:库库的里昂 🎐C/C领域新星创作者 🎉欢迎 👍点赞✍评论⭐收藏✨收录专栏:数据结构与算法🤝希望作者的文章能对你有所帮助,有不足的地方请在评论区留言指正,大家…

软件开发和软件测试,到底学哪个好呢?

写在前面:买车没有最好,只有最适合。 类似这类“很难选择”的问题,在知乎上其实有很多。 比如:“该去年薪10w的国家电网,还是去年薪40w的互联网大厂”; 比如:“城里有房,剩下的100…

Sentinel规则

一、服务熔断测试 例子: application.properties配置文件 server.port8083spring.application.nameorder#spring.cloud.nacos.discovery.server-addrhttp://192.168.44.64:80spring.cloud.nacos.discovery.server-addrlocalhost:8848spring.cloud.sentinel.transport.port999…

C++之map和set模拟实现

前言 在map和set的使用文章中提到了CSTL中的map和set的底层其实就是用的红黑树来实现的,所以可以用红黑树来简单模拟实现一下STL中的map和set. STL源码中map和set的实现 map: 我们看到它的底层这个成员变量其实就是一棵红黑树, 之前说过map其实就对应搜索树的KV模型&#x…

面向企业的人脸属性检测技术方案

人脸识别技术已经成为企业提升服务质量、优化用户体验的重要工具。美摄科技,作为领先的人工智能技术提供商,我们致力于为企业提供最先进、最全面的人脸属性检测技术解决方案。 我们的AI人脸检测与属性分析技术,能够快速准确地检测人脸并返回…

安全狗云安全体系为高校提升立体化纵深防御能力

客户情况 某高校有服务器500台,对外站点200个,核心交换流量20G。 客户痛点 校园网系统分类较多,并且每类网站中安全级重要程度又各不相同,同时有多个网络出口(如:教育网、电信网、移动网等),二级学院存在…

物联网网关在工业行业的应用案例

物联网网关在工业行业的应用案例 随着物联网技术的不断发展,物联网网关在工业行业的应用越来越广泛。本文将介绍一个物联网网关在工业行业的应用案例,以期为相关领域的研究和实践提供借鉴和启示。 一、案例背景 某大型制造企业是一家全球知名的汽车制…

vscode中git拉取、提交代码、解决冲突,以及合并代码的操作

vscode中git拉取、提交代码、解决冲突,以及合并代码的操作 场景:本地有修改代码,远程仓库没有更新,这时本地想要提交代码。 步骤:本地修改了testA文件内容->本地先暂存提交->拉取->推送; 本地修改…

2023.11.14 hivesql的容器,数组与映射

目录 https://blog.csdn.net/m0_49956154/article/details/134365327?spm1001.2014.3001.5501https://blog.csdn.net/m0_49956154/article/details/134365327?spm1001.2014.3001.5501 8.hive的复杂类型 9.array类型: 又叫数组类型,存储同类型的单数据的集合 10.struct类型…

SpringNative遇到的问题

问题1 org.apache.catalina.LifecycleException: An invalid Lifecycle transition was attempted ([before_stop]) for component 用不了反射,所以需要这个文件去 package org.wxy.example.sqlite.config;import java.lang.reflect.Constructor; import java.lan…

【机器学习基础】多元线性回归(适合初学者的保姆级文章)

🚀个人主页:为梦而生~ 关注我一起学习吧! 💡专栏:机器学习 欢迎订阅!后面的内容会越来越有意思~ 💡往期推荐: 【机器学习基础】机器学习入门(1) 【机器学习基…

BI智能财务分析真的神,财务人都来用

不用等,真的不用等!这边接入数据,那边就能把利润表、资产负债表、现金流量表等财务数据分析报表送到眼前,不用开发,直接就看分析结果。 奥威BI财务方案真能把我要的指标、分析都做出来? 能,可…

在win10环境下安装python,配置python环境,执行python脚本

1.安装python 去python官网下载: https://www.python.org/ 这里采用 Python 3.10.8 版本 选择windows 64位 双击安装: 安装这里有两个选项: 1.默认安装直接选Install Now 2.勾选install launcher for all users(recommend&a…

Github小彩蛋显示自己的README,git 个人首页的 README,readme基本语法

先上效果👇 代码在下面,流程我放最下面了,思路就是创建一个和自己同名的仓库,要公开,创建的时候会提示小彩蛋你的reademe会展示在你的首页,或许你在这个readme里面的修改都会在你的主页上看到了&#x1f44…

TEMU平台要求电子产品提供的UL测试报告如何办理?

平台销售的电子产品,要符合指定的标准,如果不合格很容易发生起火,等危及消费者生命财产的安全,因此很多客户因为缺少UL报告,导致产品被下架。 带电的产品上架亚马逊或相关的跨境电商平台都需要相关的UL报告/UL标准&…

vue-router配置

1、路由安装 npm install vue-router4 2、创建router目录 3、编辑文件且引入router包 4、main.js引入