pg事务:事务的处理

news2024/9/20 23:20:43

事务的处理

事务块

从事务形态划分可分为隐式事务和显示事务。隐式事务是一个独立的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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【学习日记2023.5.20】 之 菜品模块完善

文章目录 3. 功能模块完善之菜品模块3.1 公共字段自动填充3.1.1 问题分析3.1.2 实现思路3.1.3 代码开发1.3.1 步骤一1.3.2 步骤二1.3.3 步骤三 3.1.4 功能测试3.1.5 提交代码 3.2 新增菜品3.2.1 需求分析与设计3.2.2 代码开发3.2.2.1 文件上传实现3.2.2.2 新增菜品实现 3.2.3 功…

pg事务:快照

pg中的快照 快照&#xff08;snapshot&#xff09;是记录数据库当前瞬时状态的一个数据结构。pg数据库的快照保存当前所有活动事务的最小事务ID、最大事务ID、当前活跃事务列表、当前事务的command id等 快照数据保存在SnapshotData结构体类型中&#xff0c;源码src/include/u…

PyQt5桌面应用开发(16):定制化控件-QPainter绘图

本文目录 PyQt5桌面应用系列画画图&#xff0c;喝喝茶QPainter和QPixmapQPixmapQPainter绘制事件 一个魔改的QLabelCanvas类主窗口主程序&#xff1a; 总结 PyQt5桌面应用系列 PyQt5桌面应用开发&#xff08;1&#xff09;&#xff1a;需求分析 PyQt5桌面应用开发&#xff08;2…

深入了解vector

vector 1. vector的介绍及使用1.1 vector的介绍1.2 vector的使用1.2.1 vector的定义&#xff08;(constructor)构造函数声明&#xff09;1.2.2 vector iterator 的使用1.2.3 vector Capacity1.2.4 vector Modifiers1.2.4 vector 迭代器失效问题 2. vector模拟实现 1. vector的介…

快速排序的三种方法

今日复习了一下快速排序的算法。 hoare法 快速排序由Hoare在1960年提出。它的基本思想是&#xff1a;通过排序将需要排序的数据分割成独立的两部分&#xff0c;左边的所有数据都比右边的小&#xff0c;然后再按此方法对这两部分数据分别进行快速排序递归&#xff0c;使其变成有…

时间序列预测 | 基于秃鹰算法优化BP神经网络(BES-BP)的时间序列预测,matlab代码

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 基于秃鹰算法优化BP神经网络(BES-BP)的时间序列预测,matlab代码 评价指标包括:R2、MAE、MSE、RMSE等,代码质量极高,方便学习和替换数据。 部分源码 %% 清空环境变量 warning off % 关闭报警信息…

BurpSuite—-Spider模块(蜘蛛爬行)

本文主要介绍BurpSuite—-Spider模块(蜘蛛爬行)的相关内容 关于BurpSuite的安装可以看一下之前这篇文章&#xff1a; http://t.csdn.cn/0Qw2n 一、简介 Burp Spider 是一个映射 web 应用程序的工具。它使用多种智能技术对一个应用程序的内容和功能进行全面的清查。 Burp Spi…

基于Qt+FFmpeg的视频监控系统

github源码 需求分析 假设一个业务场景&#xff1a;每个员工工位旁有两个网络摄像头。老板需要一个员工监控软件&#xff0c;在上班时软件可以拉取RTSP视频流&#xff0c;也可以随时录制视频。这样老板就可以知道谁在摸鱼了 ◕‿◕ 为防有人上纲上线&#xff0c;在此特别声明…

【Redis】聊一下缓存双写一致性

缓存虽然可以提高查询数据的的性能&#xff0c;但是在缓存和数据 进行更新的时候 其实会出现数据不一致现象&#xff0c;而这个不一致其实可能会给业务来带一定影响。无论是Redis 分布式缓存还是其他的缓存机制都面临这样的问题。 数据不一致是如何发生&#xff1f; 数据一致…

【c语言】文件复制原理

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c语言系列专栏&#xff1a;c语言之路重点知识整合 &#x…

pg事务:事务ID

事务ID pg中每个事务都会分配事务ID&#xff0c;事务ID分为虚拟事务ID和持久化事务ID&#xff08;transactionID&#xff09;。pg的事务ID非常重要&#xff0c;是理解事务、数据可见性、事务ID回卷等等的重要知识点。 虚拟事务ID 只读事务不会分配事务ID&#xff0c;事务ID是…

【我的C++入门之旅】(下)

前言 参考前章内容【我的C入门之旅】(上) 目录 前言1.引用常引用传值、传引用效率比较引用和指针的区别 2.auto关键字使用场景 3.范围for 语法糖4.inline函数5.指针空值nullptr 1.引用 取别名&#xff0c;一块空间有多个名字或者说是一个变量有多个名字 比如&#xff1a;李逵&…

【LeetCode: 44. 通配符匹配 | 暴力递归=>记忆化搜索=>动态规划 】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

【Linux】线程详解之线程概念

前言 在我们的教材中&#xff0c;对线程给出以下的概念&#xff1a; 是进程内部的一个执行分支&#xff0c;在进程的内部运行&#xff0c;属于进程的一部分&#xff0c;比进程更加轻量化。 可能有的人看完之后都是懵的&#xff0c;什么叫在进程的内部运行&#xff0c;什么又是…

【正点原子STM32连载】 第十二章 SYSTEM文件夹介绍 摘自【正点原子】STM32F103 战舰开发指南V1.2

1&#xff09;实验平台&#xff1a;正点原子stm32f103战舰开发板V4 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第十二…

文件夹路径保存不同,什么批量修改名称

在日常工作中不知道大家有没有遇到过&#xff0c;需要批量修改文件夹名称&#xff0c;并且文件夹保存路径不同呢&#xff0c;像这种情况到底不能批量修改呢。我也问了很多身边的朋友&#xff0c;他们有的说&#xff0c;他一般都修改保存路径是同一个&#xff0c;还很少遇到像我…

【C++ STL】 趣学stackqueuepriority_queue【对话情景版】

文章目录 &#x1f4cd;前言C STL 之 stack&queue基础知识及其模拟实现&#x1f4cd;容器适配器&#x1f388;什么是适配器&#xff1f;&#x1f388;STL标准库中stack和queue的底层结构&#x1f388;deque的简单介绍(了解)&#x1f4cc;deque的原理介绍&#x1f4cc;deque…

强化学习:基本概念

以 grid-world 为例&#xff0c;进行强化学习基础概念的介绍。如图&#xff0c;机械人处于一个网格世界中&#xff0c;不同的网格代表不同的功能&#xff0c;白色代表机械人可以自由的进入&#xff0c;黄色代表陷阱&#xff08;机械人一旦进入就会被强制返回起点&#xff09;&a…

《Reinforcement Learning: An Introduction》第1章笔记

文章目录 1.1 强化学习1.2 强化学习的例子1.3 强化学习的要素1.4 局限和范围1.5 拓展例子&#xff1a;井字游戏1.6 总结1.7 强化学习的早期历史参考资料 1.1 强化学习 强化学习是学习做什么—如何将情景映射到动作—以便最大化数字奖励信号。学习者不会被告知该采取什么动作&a…

MySQL基础(三十九)MySQL常用命令

1 MySQL常用命令 1.1 mysql 该mysql不是指mysql服务&#xff0c;而是指mysql的客户端工具。 语法 &#xff1a; mysql [options] [database]1.1. 连接选项 #参数 &#xff1a; -u, --username 指定用户名 -p, --password[name] 指定密码 -h, --hostname 指定服务器IP或域名…