首页 > 数据库 >POSTGRESQL 事务控制(二) 事务开启 (写着费力,看着费劲系列)

POSTGRESQL 事务控制(二) 事务开启 (写着费力,看着费劲系列)

时间:2023-06-19 17:01:14浏览次数:45  
标签:状态 事务 CLOG POSTGRESQL PER 费劲 ID 页面


POSTGRESQL  事务控制(二) 事务开启  (写着费力,看着费劲系列)_mysql

今天接着上回书,事务如果在处理中没有子事务,则实现和控制是十分容易的,但如果有子事务的情况下, 子事务通过transactionState结构体来实现,(上次已经提到了),每一个transactionState都指向父事务的结构体的指针.

在继续往下说之前,我们的提到clog, 这是理解后面要提到的一些事情的前提, 在POSTGRESQL 中clog 是记录每一个事务相关的xid, 以及事务的提交状态, 状态包含了 执行中, 已提交, 中断,子事务已提交. 那么clog 承担了对整体事务状态的记录和查询的任务. 

下面是一段clog 代码和 xidstatus的状态结构

POSTGRESQL  事务控制(二) 事务开启  (写着费力,看着费劲系列)_mysql_02

POSTGRESQL  事务控制(二) 事务开启  (写着费力,看着费劲系列)_java_03

从上面两个图中可以得到的信息

CLOG_BITS_PER_XACT  2  一个事务使用2BIT

CLOG_XACTS_PER_BYTE 4  一个字节记录4个事务

CLOG_XACTS_PER_PAGE (BLCKSZ*CLOG_XACTS_PER_BYTE)  一个页面记录(8196*4=32784) 个事务

((xid)   (TransactionId)  CLOG_XACTS_PER_PAGE  

如果要寻找xid的页面位置,通过事务号除以一个页面的记录事务数,就得到了具体这个事务所在的页面数.

((xid) % (TransactionId) CLOG_XACTS_PER_PAGE)

下面的计算可以获得相关信息存储在页面中的第多少个字节

(TransactionIdToPgIndex(xid) / CLOG_XACTS_PER_BYTE)

最后的公式是计算事务信息存在在字节内的偏移量

 ((xid) % (TransactionId) CLOG_XACTS_PER_BYTE)

如果要知道xid事务的状态,则直接通过取余的方式直接获得事务的状态页面内的偏移位置

从上面的东西中可以获得

1  事务的状态是通过2个BITS来存储的, 每个字节可以存储4个事务的状态

2  确认当前事务的状态通过事务ID ,事务XID 是32BIT

3  通过简单的除法和商运算,可以获得事务的状态信息

我们验证一下, 我们开通4个 SESSION ,然后将SESSION中的事务ID打印出来.

分别事务id 为 623  - 626

POSTGRESQL  事务控制(二) 事务开启  (写着费力,看着费劲系列)_大数据_04

POSTGRESQL  事务控制(二) 事务开启  (写着费力,看着费劲系列)_mysql_05

下面四个计算的公式 

1 得到事务存储的页面 0号页面  

2 得到事务存储在页面总的偏移量

3 数据存储在页面内的多少字节

4 字节内的偏移量

通过事务ID 就可以直接获得事务的状态在CLOG中的存储位置,并且提取相关的信息.

POSTGRESQL  事务控制(二) 事务开启  (写着费力,看着费劲系列)_mysql_06

POSTGRESQL  事务控制(二) 事务开启  (写着费力,看着费劲系列)_java_07

那么我们来计算一下,一个8K的页面可以存储多少事务,以及事务的状态

8K页面* 8b/2b (事务的4个状态) = 32KB = 16384 个事务的状态

假设我们有5MB的内存空间,可以存储  10485760 个事务的状态,这里需要注意我们的事务动态的信息都是存在在内存中,所以用更小的内存来控制更多的事务是有利于整体运行效率的.

现在我们回归主题,子事务的与父事务的关系的存储, 在我们的pg的数据库目录里面有一个目录是pg_subtrans 目录,其中通过pg_subtrans 这个目录中的文件来存储子事务与父事务之间的关系. 子事务保存自己上一次的事务,相关事务的追述是通过自下而上的方式. 

下面是这段和pg_subtrans有关的代码, 这段代码在 xact.c 中, 这段代码的主要的作用是在给子事务上的父事务ID 进行记录, 好进行自下而上的寻根

static void
AssignTransactionId(TransactionState s)
{
    bool        isSubXact = (s->parent != NULL);
    //是否是子事务,如果有父事务,则父事务不能为空

    ResourceOwner currentOwner;
    bool        log_unknown_top = false;
    // 确认当前事务号有效并且事务是在inprogress 的状态
    Assert(!TransactionIdIsValid(s->transactionId));
    Assert(s->state == TRANS_INPROGRESS);
   
    //如果当前事务在并行则不运行分配事务号

    if (IsInParallelMode() || IsParallelWorker())
        elog(ERROR, "cannot assign XIDs during a parallel operation");

在 subtrans.c中包含关于在PG 重启后处理pg_subtrans中的数据的方法是直接清理掉这些数据,一下这段代码进行相关工作的代码.

POSTGRESQL  事务控制(二) 事务开启  (写着费力,看着费劲系列)_数据库_08

主要的原由是,子事务是包含在事务内的,在事务本身失效后,这些子事务也没有必要进行记录,所以在pg_wal中也不会有相关子事务的日志记录.

上期说到事务的ID 只有在执行 INSERT ,UPDATE ,DELETE的时候才进行事务号的分配,那么不分配事务号的情况下,事务到底有没有事务号, 实际上是有的在事务开始时是分配一个虚拟的事务ID

在开始一个事务的时候,会先开始分配内存和事务所需要的,buffer, 锁等信息,每个事务都需要有相关的resourceOwner信息, 虚拟的事务主要通过两个方式来生成自己的虚拟事务ID ,  benchend process  ID + 本地的计数器, 这样就可以产生一个自己的临时的虚拟的事务ID 

在获取了ID后,我们直接就开始进行相关事务的开启,参加下面的语句

TRACE_POSTGRESQL_TRANSACTION_START(vxid.localTransactionId);

POSTGRESQL  事务控制(二) 事务开启  (写着费力,看着费劲系列)_mysql_09

POSTGRESQL  事务控制(二) 事务开启  (写着费力,看着费劲系列)_大数据_10

此时在设置完相关的变量的初始值后, 如事务就可以开始启动了.

总结,在一个事务开启时

1  事务初始并没有实际的事务ID ,而是本地通过backend 和计数器临时分配的虚拟事务ID , 只有在事务中出现IUD 的操作才会分配实际的事务ID 

2  服务器在重启或者CRASH 后会清理与子事务与父事务相关的关联的信息

3  在事务中,存在越多的子事务,则整体的系统的性能会越来越低,所以不建议使用大量的save point 产生大量的子事务. 并且子事务与父事务之间的关系是自下而上的搜索, 只有通过子事务才能查找到自己的父事务, 并在设计的时候, 通过简单的事务ID与页面数的余数,商可以直接快速定位事务的状态.

POSTGRESQL  事务控制(二) 事务开启  (写着费力,看着费劲系列)_mysql_11

标签:状态,事务,CLOG,POSTGRESQL,PER,费劲,ID,页面
From: https://blog.51cto.com/u_14150796/6516031

相关文章

  • POSTGRESQL SERVERLESS 是POSTGRESQL 数据库的未来 (译)
    以下为翻译内容多年来,PostgreSQL一直备受瞩目,对于企业来说,POSTGRESQL流行是面临众多竞争后的选择。随着企业试图摆脱昂贵的传统关系型数据库管理系统(RDBMS),但仍希望坚持使用RDBMS,开源PostgreSQL是一种具有吸引力的、更经济实惠的替代方案。曾经有两个托管PostgreSQL服务(Aurora和RDS)......
  • POSTGRESQL NEON - Serverless 式的POSTGRESQL 数据库的独特技能 分支数据
    之前没有关注过SERVERLESS的数据库产品之前,我很少会关注SERVERLESS的东西,因为一直在实体机数据库类型打拼的我,从来不关心什么 云原生什么SERVERLESS,Idon'tcareaboutthat,it'snotmybusiness!!!!但是后来上云了,上的很深,没法了,开始关注什么是云原生,什么是POALRDB 最......
  • PostgreSql通过创建外部表而非dblink使访问速度提高,优化sql查询速度
    resourceregister库外部表创建--导入插件createextensionpostgres_fdw;--创建服务名称为operation的服务host为ipport为端口dbname为数据库名称createserveroperationforeigndatawrapperpostgres_fdwoptions(host'localhost',port'5432',dbname'operat......
  • 事务扩展机制TransactionSynchronization
    事务扩展机制TransactionSynchronization在进行数据库操作的时候,如果需要多个操作要么一起成功,要么一起失败那么就需要使用事务操作了。使用Spring框架只需要在方法上添加 @Transactional 注解这个方法就具有事务特性了。而且Spring也事务操作给开发者提供了很方便的扩展......
  • PostgreSQL
    PostgreSQLPostgreSQL的介绍开源的关系型数据库官方社区网址:https://www.postgresql.org/中文社区网址:http://www.postgres.cn/docs/12/1.支持大部分SQL标准并且提供了许多现代特性:复杂查询外键触发器可更新视图事务完整性多版本并发控2.P......
  • 【Java学习】 Spring的基础理解 IOC、AOP以及事务
    一、简介  官网: https://spring.io/projects/spring-framework#overview   官方下载工具: https://repo.spring.io/release/org/springframework/spring/  github下载: https://github.com/spring-projects/spring-framework   maven依赖:<dependency>......
  • macOS 安装 postgreSQL
    PostgreSQLDocumentationbrewinstallpostgresqlbrewservicesstartpostgresqlcreatedb#Bydefault,adatabasewiththesamenameasthecurrentuseriscreated.#dropdbpsql......
  • PostgreSQL 已领先于 MySQL 成为开发人员的首选
    一项针对90,000名开发人员的调查显示,PostgreSQL领先于MySQL作为数据库引擎的选择,与去年的同一项调查相比有显着变化。2023年5月的调查由开发人员问答网站StackOverflow进行,有45.55%的受访者使用PostgreSQL,而MySQL和SQLite分别为41.09%和30.9%。三年前,同一......
  • 深入浅出MySQL事务
    PhotobyLukasHartmannfromPexels辞职这段时间以来看见了很多工作之外的东西,我认为这是值得的。同时也有时间和机会来好好整理所学所想,准备开启下一段旅途。事务的定义及特性数据库事务代表在数据库管理系统(或类似系统)中对数据库进行的一致可靠的工作单元,独立于其他事......
  • 【分布式事务】实现分析
    需解决的问题:事务状态的流转:状态机子事务失败时:如何触发重试、重试失败后整个事务的回滚(补偿时如何调用客户端补偿方法)异常场景:空回滚、悬挂、幂等(业务要考虑幂等问题)监控:快速定位(找到当前事务的所有处理日志)、集群事务处理能力大盘高可用设计:失效转移,处理事务的节点异常后,不......