pg事务:子事务

news/2024/5/16 1:48:42/文章来源:https://blog.csdn.net/qq_40687433/article/details/130783474

什么是子事务?

一般事务只能整体提交或回滚,而子事务允许部分事务回滚。

SAVEPOINT p1 在事务里面打上保存点标记。不能直接提交子事务,子事务也是通过事务的提交而提交。不过可以通过ROLLBACK TO SAVEPOINT p1回滚到该保存点。

子事务在大批量数据写入的时候很有用。如果事务中存在多个子事务,而其中一小段子事务失败,只需要重做这小部分数据就行,而不需要整个事务数据全部重做。

子事务在SQL语句中的使用

SAVEPOINT savepoint_name
ROLLBACK [ WORK | TRANSACTION ] TO [ SAVEPOINT ] savepoint_name
RELEASE [ SAVEPOINT ] savepoint_name

注意:

  • savepoints语句必须在事务块中
  • savepoint执行保存点;rollback回滚到指定保存点;release擦除保存点,不会回滚子事务数据
  • cursor不会被savepoint事务影响

sql中的子事务示例:

lzldb=# begin;
BEGIN
lzldb=*#  insert into lzl1 values(0);
INSERT 0 1
lzldb=*# savepoint p1;
SAVEPOINT
lzldb=*#  insert into lzl1 values(1);
INSERT 0 1
lzldb=*# savepoint p2;
SAVEPOINT
lzldb=*# insert into lzl1 values(2);
INSERT 0 1
lzldb=*# savepoint p3;
SAVEPOINT
lzldb=*# insert into lzl1 values(3);
INSERT 0 1
lzldb=*# rollback to savepoint p2;
ROLLBACK
lzldb=*# commit;
COMMIT
lzldb=# select xmin,xmax,cmin,a from lzl1;xmin | xmax | cmin | a 
------+------+------+---731 |    0 |    0 | 0732 |    0 |    1 | 1
(2 rows)
--回滚到p2时,p3也被回滚lzldb=# select * from vlzl1;t_ctid | lp | lp_flags  | t_xmin | t_xmax | t_cid |                      raw_flags                       | combined_flags 
--------+----+-----------+--------+--------+-------+------------------------------------------------------+----------------(0,1)  |  1 | LP_NORMAL |    731 |      0 |     0 | {HEAP_HASNULL,HEAP_XMIN_COMMITTED,HEAP_XMAX_INVALID} | {}(0,2)  |  2 | LP_NORMAL |    732 |      0 |     1 | {HEAP_HASNULL,HEAP_XMIN_COMMITTED,HEAP_XMAX_INVALID} | {}(0,3)  |  3 | LP_NORMAL |    733 |      0 |     2 | {HEAP_HASNULL,HEAP_XMIN_INVALID,HEAP_XMAX_INVALID}   | {}(0,4)  |  4 | LP_NORMAL |    734 |      0 |     3 | {HEAP_HASNULL,HEAP_XMIN_INVALID,HEAP_XMAX_INVALID}   | {}
(4 rows)
--子事务infomask跟一般事务区别不大,同一个事务中多个命令通过cid和HEAP_XMIN_INVALID等就可以判断可见性
--子事务产生写入同样会消耗transaction id,而且cid在父事务框架下增加

其他场景中产生子事务

即使不用savepoint,也有其他方法产生子事务

  • EXCEPTION语句会触发子事务,这在一些工具或架构中常见,也很容易被忽略。每次EXCEPTION都会产生一个子事务。

语法如:BEGIN / EXCEPTION WHEN .. / END

参考:https://fluca1978.github.io/2020/02/05/PLPGSQLExceptions.html

  • PL/Python代码引用plpy.subtransaction()

子事务SLRU缓存

子事务提交日志在pg_xact,父子对应关系在pg_subtrans存储子事务缓存subXID和父XID的映射。当PostgreSQL需要查找subXID时,它会计算这个ID驻留在哪个内存页中,然后在内存页中进行搜索。如果页面不在缓存中,它会驱逐一个页面,并将所需的页面从pg_subtrans加载到内存中。大量的子事务cache miss会消耗系统的IO和cpu。

子事务用的buffer只有32个并在源码中写死

源码src/include/access/subtrans.h

/* Number of SLRU buffers to use for subtrans */
\#define NUM_SUBTRANS_BUFFERS    32

buffer默认为8k,xid是32位占4个bytes,所以

SUBTRANS_BUFFER大小为32*8k=256k

SUBTRANS_BUFFER能存储最多32*8k/4=65536个xid

在这里插入图片描述

通过transactionid找到子事务的在page中的位置
源码src/backend/access/transam/subtrans.c

/* We need four bytes per xact */
#define SUBTRANS_XACTS_PER_PAGE (BLCKSZ / sizeof(TransactionId))
//每个页面最多存储8k/4bytes=2048个子事务id#define TransactionIdToPage(xid) ((xid) / (TransactionId) SUBTRANS_XACTS_PER_PAGE)
//通过子事务xid计算page号=xid/2048
#define TransactionIdToEntry(xid) ((xid) % (TransactionId) SUBTRANS_XACTS_PER_PAGE)
//通过子事务xid计算在page中的offset=xid%2048

子事务xid在page中不一定是紧凑的,一个page可能少于2048个子事务id

子事务的危害

  1. PGPROC_MAX_CACHED_SUBXIDS溢出

PGPROC_MAX_CACHED_SUBXIDS不是GUI参数,在源码中写死,只能通过改源码修改该参数。

源码src/include/storage/proc.h

	/* *每个backend都有子事务cache上限PGPROC_MAX_CACHED_SUBXIDS。*我们必须跟踪cache是否溢出(比如,事务至少有一个缓存不了的子事务)*如果一个cache都没有溢出,我们可以确认没有在pgproc array中xid一定不是一个运行中的事务。*(没有在任何proc,又没有溢出,说明没有跑)*如果有溢出,我们必须查看pg_subtrans*/#define PGPROC_MAX_CACHED_SUBXIDS 64	/* XXX guessed-at value */struct XidCache{TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS];};

阅读这段源码,得到两个重要信息

  • 每个backend都有子事务cache为PGPROC_MAX_CACHED_SUBXIDS,固定64个子事务
  • 超过64个子事务会溢出到pg_subtrans目录

copy大佬压测:子事务刚好超过64个的时候,性能下降。所以,每个会话的子事务最好不要超过64个

在这里插入图片描述

  1. 子事务导致multixact异常等待

原文:https://buttondown.email/nelhage/archive/notes-on-some-postgresql-implementation-details/

for update本身是行级排他锁,本身不应该产生multixact id,但在此场景中产生了多个MultiXact等待,导致数据库性能断崖

  • LWLock:MultiXactMemberControlLock
  • LWLock:MultiXactOffsetControlLock
  • LWLock:multixact_member
  • LwLock:multixact_offset

后来发现在Django框架中有子事务语句

SELECT [some row] FOR UPDATE;SAVEPOINT save;UPDATE [the same row];
  1. 从库性能急剧下降

原文:https://about.gitlab.com/blog/2021/09/29/why-we-spent-the-last-month-eliminating-postgresql-subtransactions/

一个长事务和一个savepoint子事务也可能造成查询库性能断崖

如果读取发生在主库的快照上,则生成的快照包含xmin,xmax,txip事务列表,subxip保存一个在进行的子事务列表。但是,无论是原数组还是快照都不会直接与从库共享,从库从WAL中读取所需的所有数据

在这里插入图片描述

当存在子事务时,一个长事务的运行会使从库性能断崖式下滑

在这里插入图片描述

  1. 生产性能急剧下降

当数据库运行繁忙,又存在较多子事务时,性能可能急剧下降,并伴随子事务的等待事件。这个场景即使每个会话子事务没有超过64,而且不是在从库而是在主库上时,也会发生。

我们发现工具(OGG)中默认是50个子事务,此时我们将工具中的子事务数据量降低到10-20个时,数据库性能得到缓解。

子事务的使用建议

  • 除了显示savepoint使用子事务,excetpion、框架、工具中同样会产生子事务
  • 如果有从库查询业务,禁止使用子事务。
  • 谨慎使用行锁。for update+子事务同样会引起multixactid的问题
  • 如果仍有子事务,子事务设置不要超过64个,最好是更低

子事务已经在国内外生产环境造成了非常多问题,有许多案例和问题分析。引用一下“Subtransactions are basically cursed. Rip em out.”

子事务参考

https://postgres.ai/blog/20210831-postgresql-subtransactions-considered-harmful

https://www.cybertec-postgresql.com/en/subtransactions-and-performance-in-postgresql/

https://fluca1978.github.io/2020/02/05/PLPGSQLExceptions.html

https://about.gitlab.com/blog/2021/09/29/why-we-spent-the-last-month-eliminating-postgresql-subtransactions/

https://buttondown.email/nelhage/archive/notes-on-some-postgresql-implementation-details/

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

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

相关文章

【场景方案】如何去设计并二次封装一个好用的axios,给你提供一个好的参考(1.0版)

文章目录 前言文件结构建议封装的文件结构接口管理文件 二次封装axios的初始配置initutilswebConfig 再封一层环境配置使用 前言 以下演示基于vue3与element-plus 文件结构建议 封装的文件结构 把二次封装axios所有有关的代码全部放在request文件夹中,其中init.js…

【TypeScript】TS中type和interface在类型声明时的区别

🐱 个人主页:不叫猫先生 🙋‍♂️ 作者简介:2022年度博客之星前端领域TOP 2,前端领域优质作者、阿里云专家博主,专注于前端各领域技术,共同学习共同进步,一起加油呀! 💫优质专栏:vue3+vite+typeScript从入门到实践 📢 资料领取:前端进阶资料可以找我免费领取 …

南京邮电大学算法与设计实验二:贪心算法(最全最新,与题目要求一致)

三、实验原理及内容 实验原理: 1、用贪心法实现求两序列的一般背包问题。要求掌握贪心法思想在实际中的应用,分析一般背包的问题特征,选择算法策略并设计具体算法,编程实现贪心选择策略的比较,并输出最优解和最优解值。…

机器学习项目实战-能源利用率 Part-4(模型构建)

博主前期相关的博客可见下: 机器学习项目实战-能源利用率 Part-1(数据清洗) 机器学习项目实战-能源利用率 Part-2(探索性数据分析) 机器学习项目实战-能源利用率 Part-3(特征工程与特征筛选) 这…

【JVM】6. 堆

文章目录 6.1. 堆(Heap)的核心概述6.1.1. 堆内存细分6.1.2. 堆空间内部结构(JDK7)6.1.3. 堆空间内部结构(JDK8) 6.2. 设置堆内存大小与OOM6.2.1. 堆空间大小的设置6.2.2. OutOfMemory举例 6.3. 年轻代与老年…

如何在IDEA中显示时序图

如何在IDEA中显示时序图 有时候,我们想要了解代码的运行过程的时候,想要看到方法的调用流程。 这个时候就希望有一个时序图可以看,但是人工来画时序图太麻烦了,有没有办法在IDEA中直接生成呢? 当然是可以的。 这里…

知识积累(1)

(1) 当您在Git中看到消息 "HEAD is now at 1343ccb FAB-17419 Fix off_chain_data sample error (#146)" 时,这是Git告知您当前所在的分支和最新的提交哈希。 这条消息通常出现在使用Git命令后,如git pull或git check…

【我的创作纪念日】—— 纪念四年的坚持

这是一篇和技术无关的博客,但对我而言,它承载了不菲的价值 普通且宁静的一天,被一条消息戳中,于是,写一篇分享帖,纪念我这 1460 天的坚持初衷: 前言:对过去的回顾 4 年前的我&#…

Python图片转字符画,太好玩啦(46)

小朋友们好,大朋友们好! 我是猫妹,一名爱上Python编程的小学生。 和猫妹学Python,一起趣味学编程。 今日主题 什么是字符画呢? 如何用Python将图片转为字符画? 我们先找一幅原画,比如它吧&…

卡方检验.医学统计实例详解

卡方检验是一种常用的假设检验方法,通常用于分析两个或多个分类变量之间的关系。在医学研究中,卡方检验被广泛应用于分析两种或多种治疗方法的疗效,或者分析某种疾病的发病率与某些危险因素之间的关系。下面我们来看一个卡方检验在医学实例中…

WALN网络不存在? 离谱事件解决方法

前情: 本来在高高兴兴赶ddl,突然发现网断了。尝试重连,显示无法连接... 遂重启,结果事情更糟了,WALN就没了,没了,没了... 这张是修好之后的图,但是当时所有包括蓝牙,waln…

13-2-CSS3-渐变色、2D转换、3D转换

一、渐变色 CSS渐变色(Gradient)是指在元素背景中使用两种或多种不同的颜色进行过渡,超过两个颜色可以形成更为细腻的渐变效果。常见的CSS渐变色有线性渐变和径向渐变。 1. 线性渐变:Linear Gradients 向下/向上/向左/向右/对角…

t检验与Z检验的区别

在统计学中,假设检验是评估某种特定情况下观察到的数据是否符合假设的一种方法。t检验和Z检验是两种常用的假设检验方法,分别用于比较均值差异以及比例差异。在医学统计中,t检验和Z检验经常被用于研究和比较不同治疗方法的效果,例…

基于MAC地址的ACL配置

基于MAC地址的ACL配置 【实验目的】 掌握基于MAC地址的标准ACL的配置。验证配置。 【实验拓扑】 实验拓扑如图1所示。 图1 实验拓扑 设备参数如表所示。 表1 设备参数表 设备 接口 IP地址 子网掩码 默认网关 S1 e0/0 N/A N/A N/A e0/1 N/A N/A N/A PC1 N/…

IntelliJ 导出和导入配置文件

导出: File->Manage IDE Setting->Export Settings…->选择导出目录,可以得到一个 settings.zip 的文件 导入方法: File->Manage IDE Setting->Import Settings…->选择需要导入的文件即可,导入之后重启IDE。

chatgpt赋能Python-pythonfind

Python文件搜索工具Pythonfind 在开发过程中,文件搜索工具是一个非常重要的工具。在大型项目中,可能需要查找特定类型的文件或者在代码库中查找特定的代码块。 Pythonfind是一个非常强大和灵活的python文件搜索工具,可以帮助我们简化这个过程…

Go 语言核心编程-环境入门篇

第 1 章 Golang 开山篇 1.1 Golang 的学习方向 Go 语言,我们可以简单的写成 Golang 1.2 Golang 的应用领域 1.2.1区块链的应用开发 1.2.2后台的服务应用 1.2.3云计算/云服务后台应用 1.3 学习方法的介绍 1.4 讲课的方式的说明 努力做到通俗易懂注重 Go 语言体系&…

云从科技从容大模型:大模型和AI平台什么关系?为什么造行业大模型?

原创:亲爱的数据 2023年5月18日,坐标广州南沙,来自云从科技的“云从从容大模型”正式亮相。 自此,云从科技从CV四小龙“进阶”成为一家AI大模型公司,同时,别忘记云从还有一个身份常被人提起:首家…

python 文件操作 , 异常处理 , 模块和包

文件操作 1.写数据 # open(name, mode) # name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径)。 # mode:设置打开文件的模式(访问模式):只读、写入、追加等。 #1.打开文件---通道建立--申请资源 # w 模式会清空之前的内…

C++13-STL模板

C13-STL模板 在线练习: http://noi.openjudge.cn/ https://www.luogu.com.cn/ 大纲要求 【 3 】算法模板库中的函数:min、max、swap、sort 【 4 】栈 (stack)、队列 (queue)、链表 (list)、 向量(vector)等容器 1.函数模板 泛…