pg事务:事务的处理

事务的处理

事务块

从事务形态划分可分为隐式事务和显示事务。隐式事务是一个独立的SQL语句,执行完成后默认提交。显示事务需要显示声明一个事务,多个sql语句组合到一起称为一个事务块。

事务块通过beginbegin transactionstart transaction开始

通过COMMIT,ENDABORT,ROLLBACK结束,其中COMMIT=ENDABORT=ROLLBACK

BEGIN;
select * from lzl1 limit 1;
update lzl1 set a=2;
END;

如果事务块执行过程中一旦有报错,由于事务必须满足原子性,事务只能回退

lzldb=# begin;
BEGIN
lzldb=*# select * from lzl2;
ERROR: relation "lzl2" does not exist
LINE 1: select * from lzl2;
^
lzldb=!# commit;
ROLLBACK

事务处理函数

事务处理函数分为3个层次:顶层事务函数、中层事务函数、底层事务函数
顶层事务函数,处理事务块命令,比如BEGIN, COMMIT, ROLLBACK, SAVEPOINT等,有如下函数

BeginTransactionBlock启动事务块
EndTransactionBlock结束事务块
UserAbortTransactionBlock用户显示结束事务块
DefineSavepoint生成保存点
RollbackToSavepoint回滚到某保存点
ReleaseSavepoint释放保存点

中层事务函数,每个sql在执行前后都会调用中层事务函数,包括检测到异常后,有如下函数

StartTransactionCommand启动事务命令
CommitTransactionCommand完成事务命令,注意不是提交命令
AbortCurrentTransaction退出当前事务

底层事务函数,真正的事务处理函数,负责维护事务状态、事务资源分配和回收等,有如下函数

StartTransaction启动事务
CommitTransaction提交事务
AbortTransaction回滚/中断事务
CleanupTransaction清理事务
StartSubTransaction启动子事务
CommitSubTransaction提交子事务
AbortSubTransaction回滚/中断子事务
CleanupSubTransaction清理子事务

其实这上面几个函数还是比较好分辨的。抛开几个特殊的函数(上层相关savepoint,中层abort函数),其实上、中、下三层事务层分成了:*Block(事务块函数),*Command(command函数),*Transaction(真正的事务处理函数)。然后把savepoint子事务当做事务块函数(后面会介绍,子事务可以在事务块中回退,所以这里把子事务放在事务块一级理所当然),把abort命令当做command级函数就可以了。

事务块状态

上层函数和中层函数同时控制事务块状态,底层函数控制事务状态

事务块状态和事务状态均在src/backend/access/transam/xact.c

typedef enum TBlockState
{
/* 不在事务块中的状态 */
TBLOCK_DEFAULT,                /* 空闲状态,事务开始或结束后都处于此状态 */
TBLOCK_STARTED,                /* 刚开始进入事务块时的状态,由TBLOCK_DEFAULT转换到此状态,此状态存在时间较短 */
 
/* 事务块状态 */
TBLOCK_BEGIN,                /* 启动事务块,此时才启动数据块,进入数据块级状态 */
TBLOCK_INPROGRESS,            /* 活跃的事务,BEGIN以后事务块一直处于此状态,直到事务结束 */
TBLOCK_IMPLICIT_INPROGRESS, /* 隐式BEGIN的活跃事务 */
TBLOCK_PARALLEL_INPROGRESS, /* 并行执行的活跃事务 */
TBLOCK_END,                    /* 收到COMMIT命令 */
TBLOCK_ABORT,                /* 事务失败,等待ROLLBACK */
TBLOCK_ABORT_END,            /* 事务失败,收到ROLLBACK */
TBLOCK_ABORT_PENDING,        /* 活跃事务,收到ROLLBACK */
TBLOCK_PREPARE,                /* 活跃事务,收到PREPARE(显式2PC) */

/* 子事务状态(仍然是事务块级状态) */
TBLOCK_SUBBEGIN,            /* 启动子事务 */
TBLOCK_SUBINPROGRESS,        /* 活跃的子事务 */
TBLOCK_SUBRELEASE,            /* 收到RELEASE(释放保存点) */
TBLOCK_SUBCOMMIT,            /* 当子事务还在运行的时候(SUBINPROGRESS),收到父事务COMMIT */
TBLOCK_SUBABORT,            /* 失败子事务,等待rollback命令 */
TBLOCK_SUBABORT_END,        /* 失败子事务,收到rollback命令 */
TBLOCK_SUBABORT_PENDING,    /* 活跃子事务,收到rollback命令 */
TBLOCK_SUBRESTART,            /* 活跃子事务,收到rollback to命令 */
TBLOCK_SUBABORT_RESTART        /* 失败子事务,收到ROLLBACK TO命令 */
} TBlockState;

大部分状态是显而易见的。需要补充说明的是事务回滚(rollback)和事务失败(ABORT)两者后续行为是相似的,他们都要把清理事务资源和退出当前事务。但是pg把他们分为了两种行为,设置了两种状态TBLOCK_ABORTTBLOCK_ABORT_END(子事务亦然),为什么会这样呢?

src/backend/access/transam/README中对此现象作了详细的说明:

场景 1场景 2
1) 用户输入 BEGIN1) 用户输入 BEGIN
2) 用户执行某些命令2) 用户执行某些命令
3) 用户不喜欢她所看到的东西,输入ABORT3) 事务系统因为某些原因中断(语法错误等)

场景1中,我们想中断事务并把事务回退到default状态 。

场景2中,可能后续还会有更多的命令,这些命令也是当前事务块的一部分,我们不得不忽略这些命令,直到我们看见COMMIT or ROLLBACK

AbortCurrentTransaction处理事务内部中断,UserAbortTransactionBlock处理事务用户中断。两个函数都依赖AbortTransaction来处理所有真正的工作。唯一区别在于AbortTransaction工作结束后我们进入了什么状态:

* AbortCurrentTransaction leaves us in TBLOCK_ABORT

* UserAbortTransactionBlock leaves us in TBLOCK_ABORT_END(原文如此,不过用户输入结束应该进入TBLOCK_ABORT_PENDING状态

底层事务中断处理分为两个阶段:

* 一旦我们意识到事务失败,就会执行AbortTransaction。这应该释放所有共享资源(锁等),以防不必要的增加其他backends的延迟。

* 当我最终看到用户COMMIT或者ROLLBACK时,执行CleanupTransaction;该函数将清理资源并让我们完全跳出事务。特别是,在此之前我们不能破坏TopTransactionContext

事务状态

事务状态一目了然(注意跟事务块状态是不同的)

typedef enum TransState
{
TRANS_DEFAULT,                /* 空闲 */
TRANS_START,                /* 事务启动 */
TRANS_INPROGRESS,            /* 活跃的事务 */
TRANS_COMMIT,                /* 事务提交 */
TRANS_ABORT,                /* 退出事务 */
TRANS_PREPARE                /* prepare事务(2pc) */
} TransState;

事务状态流转

事务块中的一个个命令,调用事务函数,事务函数转变事务、事务块的状态
以一个最简单的事务块举例(参考readme)

1)BEGIN
2)SELECT * FROM foo
3)INSERT INTO foo VALUES (...)
4)COMMIT

命令调用关系:

  	/  StartTransactionCommand;    --中层事务命令启动函数
   /    StartTransaction;        --底层真正处理启动事务函数
1)<  ProcessUtility;         --ProcessUtility处理BEGIN命
   \    BeginTransactionBlock;     --顶层事务块启动函数
    \ CommitTransactionCommand;    --中层完成命令函数  
		 
    /  StartTransactionCommand;    --中层事务命令启动函数
2) /  PortalRunSelect;        --SELECT语句执行
   \  CommitTransactionCommand;    --中层完成命令函数
    \    CommandCounterIncrement;    --中层完成命令函数
    
    /  StartTransactionCommand;    --中层事务命令启动函数
3) /  ProcessQuery;          --INSERT语句执行
   \  CommitTransactionCommand;    --中层完成命令函数
    \    CommandCounterIncrement;    --命令计数器计数+1

      / StartTransactionCommand;    --中层事务命令启动函数
     /  ProcessUtility;         --ProcessUtility处理commit命令
 4) <    EndTransactionBlock;      --调用顶层事务块结束函数
     \  CommitTransactionCommand;    --中层完成命令函数
      \   CommitTransaction;       --底层真正处理提交事务函数
  • 事务块的每一个命令,都会以中层函数StartTransactionCommandCommitTransactionCommand开始和结束
  • 在以上两个中层函数中间,可以看成真正执行的命令处理

2)SELECT和3)INSERT事务块状态都是TBLOCK_INPROGRESSBEGINCOMMIT状态块转换流程如下:

在这里插入图片描述

事务函数参考

《postgresql技术内幕》
src/backend/access/transam/README

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

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

相关文章

QT学习记录(三)绘图

按照下面两个教程学习 QT学习教程&#xff08;全面&#xff09;_Strive--顾的博客-CSDN博客_qt学习 天山老妖S的博客_QT开发(3)_51CTO博客 1、绘图 VC项目右键增加QT GUI Class&#xff0c;在QT Designer中编辑DlgDraw.ui 在DlgDraw中重载函数 void DlgDraw::paintEvent(Q…

C++之堆排

堆排的原理和结构&#xff1a; 堆排序是一种常见的排序算法&#xff0c;基于堆这种数据结构实现。堆是一种特殊的树形数据结构&#xff0c;它满足以下两个条件&#xff1a; 堆是一棵完全二叉树。 堆的任意节点的值&#xff0c;都必须大于等于&#xff08;或小于等于&#xff0…

基于ROS2的costmap中Obstacle Layer中对障碍物信息的增加与删除机制的方案调研。

文章目录 1.背景2.目标3. 障碍物信息添加方式发送数据的数据结构与接收数据的数据结构 4. 障碍物清理机制4.1 可调参数4.2 优化光追算法4.3 障碍物跟踪 1.背景 基于costmap地图&#xff0c;使用navigation导航时&#xff0c;会出现由于激光雷达/图像测距的局限性&#xff0c; …

由浅入深Netty粘包与半包解决方案

目录 1 粘包现象2 半包现象3 现象分析4 解决方案4.1 方法1&#xff1a;短链接4.2&#xff1a;方法2&#xff1a;固定长度4.3 方法3&#xff1a;固定分隔符4.4 方法4&#xff1a;预设长度 1 粘包现象 服务端代码 public class HelloWorldServer {static final Logger log Logg…

【libcurl 】win32 构建 Release版本 修改cmakelist 链接openssl1.1.*

以下库均已MD的构建以vs2019 V142构建MD构建 直接换用了一个openssl库,libcurl连接报错 $(ProjectDir)..\..\..\3rdparty\openssl\xdw_openssl1_1_1\lib\win32\libcrypto.lib

【Unity】 UI自适应案例

UI自适应案例 案例一:背包自动布局1. 创建背包面板2. 背包子项自动布局3. C#代码:动态添加子项到背包中案例二:文字自适应高度1. 创建文字面板2. 组件基本设置3. C#代码:动态更新文字并自适应高度案例一:背包自动布局 需求:动态添加背包组件,设定每行特定个数并自动匹配…

C++学习之路-变量和基本内置类型

变量和基本内置类型 一、基本内置类型1.1 算数类型1.2 带符号类型和无符号类型1.3 类型转换含有无符号类型的表达式 1.4 字面值常量整形和浮点型字面值字符和字符串字面值转义序列指定字面值的类型 二、变量2.1 变量的定义初始化列表初始化默认初始化 2.2 变量声明和定义的关系…

彻底理解粘性定位 - position: sticky(IT枫斗者)

彻底理解粘性定位 - position: sticky 介绍 粘性定位可以被认为是相对定位(position: relative)和固定定位(position: fixed)的混合。元素在跨越特定阈值前为相对定位&#xff0c;之后为固定定位。例如: .sticky-header { position: sticky; top: 10px; }在 视口滚动到元素…

python处理字符串、文本实例及注释

1、多个界定符切割字符串 代码 line = asdf fjdk; afed, fjek,asdf, foo import re re.split(r[;,\s]\s*, line) 结果 在上面的例子中,分隔符可以是逗号,分号或者是空格,并且后面紧跟着任意个的空格。只要这个模式被找到,那么匹配的分隔符两边的实体都会被当成是结果中…

【数据结构与算法】- 期末考试

课程链接: 清华大学驭风计划 代码仓库&#xff1a;Victor94-king/MachineLearning: MachineLearning basic introduction (github.com) 驭风计划是由清华大学老师教授的&#xff0c;其分为四门课&#xff0c;包括: 机器学习(张敏教授) &#xff0c; 深度学习(胡晓林教授), 计算…

可算是熬出头了,测试6年,费时8个月,入职阿里,涨薪14K

前言 你的努力&#xff0c;终将成就无可替代的自己。 本科毕业后就一直从事测试的工作&#xff0c;和多数人一样&#xff0c;最开始从事点点点的工作&#xff0c;看着自己的同学一步一步往上走&#xff0c;自己还是在原地踏步&#xff0c;说实话这不是自己想要的状态。 一年半…

在 Android 手机上恢复出厂设置后恢复照片的 4 种简单方法(新方法)

“嗨&#xff0c;谁能帮我恢复我的照片&#xff0c;因为我不小心恢复了出厂设置&#xff0c;而且我没有做备份&#xff1f;几个月来我一直试图通过使用恢复软件来恢复我的照片&#xff0c;root 了一个深扫描&#xff0c;但没用……” 恢复出厂设置可以清除电子设备的所有信息并…

Linux安装Redis数据库,无需公网IP实现远程连接

文章目录 1. Linux(centos8)安装redis数据库2. 配置redis数据库3. 内网穿透3.1 安装cpolar内网穿透3.2 创建隧道映射本地端口 4. 配置固定TCP端口地址4.1 保留一个固定tcp地址4.2 配置固定TCP地址4.3 使用固定的tcp地址连接 转发自cpolar内网穿透的文章&#xff1a;公网远程连接…

连续签到积分兑换试用流量主小程序开发

每日签到积分兑换试用流量主小程序开发 打卡兑奖小程序。用户签到活得积分。积分可以兑换商品。观看激励视频广告可以积分翻倍。 用户可以参加试用商品活动参加试用需要提交信息。可以通过分享方式直接获取试用资格。 以下是流量主小程序的功能列表&#xff1a; 广告位管理&a…

Java流程控制(一)

⭐ 控制语句⭐ 条件判断结构(选择结构)⭐ switch 语句 做任何事情事情都要遵循一定的原则&#xff0c;毕竟不以规矩&#xff0c;不成方圆&#xff0c;例如&#xff0c;到图书馆去借书&#xff0c;就必须要有借书证&#xff0c;并且借书证不能过期&#xff0c;这两个条件缺一不可…

Spring Boot 日志处理

Spring Boot 日志处理 Spring Boot 是一个非常流行的 Java 开发框架&#xff0c;它提供了简洁的配置和强大的开发工具。日志是应用程序中必不可少的一部分&#xff0c;因为它可以帮助开发人员进行调试和故障排除。Spring Boot 提供了多种日志框架&#xff0c;本文将重点介绍如…

Java泛型基本知识附面试题

一次平平无奇的面试 为什么要写这篇文档&#xff0c;主要就是在字节二面的时候&#xff0c;面试官提了这么一个问题 面试官&#xff1a;Java中的List<Integer>里有可能存String类型元素吗&#xff1f; 当时的我&#xff1a;应该…不可以吧&#xff0c;好像编译器会报错…

跟我一起使用 compose 做一个跨平台的黑白棋游戏(4)移植到compose-jb实现跨平台

前言 在上一篇文章中&#xff0c;我们已经实现了游戏的所有界面和逻辑代码&#xff0c;并且在 Android 上已经可以正常运行。 这篇文章我们将讲解如何将其从使用 jetpack compose 修改为使用 compose-jb 从而实现跨平台。 老规矩&#xff0c;先看效果图&#xff1a; 可以看到…

BurpSuite—-Target模块(目标模块)

前言 本文主要介绍BurpSuite—-Target模块(目标模块)的相关内容 关于BurpSuite的安装可以看一下之前这篇文章&#xff1a; http://t.csdn.cn/cavWt Target功能 目标工具包含了SiteMap&#xff0c;用你的目标应用程序的详细信息。它可以让你定义哪些对象在范围上为你目前的工…

「车型分析」控制系统典型应用车型 —— 辊筒AGV

辊筒AGV (Roller conveyor ) 是一种常见的AGV机器人类型&#xff0c;它利用辊筒和轮子在巷道中实现货物的搬运和运输&#xff0c;可实现托盘物品的卸载和运输等功能, 具有更高的灵活性、适应性和效率。本文将基于这款市场上常见的AGV进行一次简单的介绍。 1 车型介绍: 辊筒AGV…