当前位置: 首页 > article >正文

PostgreSQL数据库事务系统——获取事务ID

在这里插入图片描述

获取事务ID

AssignTransactionId用于向给定的TransactionState填充新的FullTransactionId。事务底层状态此刻必须为TRANS_INPROGRESS。在PG并行worker中不能分配XID。
Assigns a new permanent FullTransactionId to the given TransactionState. We do not assign XIDs to transactions until/unless this is called. Also, any parent TransactionStates that don’t yet have XIDs are assigned one; this maintains the invariant that a child transaction has an XID following its parent’s.

static void AssignTransactionId(TransactionState s) {bool		isSubXact = (s->parent != NULL);  // 是否处于子事务中ResourceOwner currentOwner;bool		log_unknown_top = false;/* Assert that caller didn't screw up */Assert(!FullTransactionIdIsValid(s->fullTransactionId)); Assert(s->state == TRANS_INPROGRESS);/* Workers synchronize transaction state at the beginning of each parallel operation, so we can't account for new XIDs at this point. */if (IsInParallelMode() || IsParallelWorker())elog(ERROR, "cannot assign XIDs during a parallel operation");

如果在子事务中,必须确保父事务有XID,所以子事务的XID拥有落后于父事务。这边对父事务分配XID的逻辑可以参考张树杰的深度理解事务书籍。

	/* Ensure parent(s) have XIDs, so that a child always has an XID later than its parent.  Mustn't recurse here, or we might get a stack overflow if we're at the bottom of a huge stack of subtransactions none of which have XIDs yet. */if (isSubXact && !FullTransactionIdIsValid(s->parent->fullTransactionId)) {TransactionState p = s->parent;TransactionState *parents;size_t		parentOffset = 0;parents = palloc(sizeof(TransactionState) * s->nestingLevel);while (p != NULL && !FullTransactionIdIsValid(p->fullTransactionId)) {parents[parentOffset++] = p;p = p->parent;}/* This is technically a recursive call, but the recursion will never be more than one layer deep. */while (parentOffset != 0) AssignTransactionId(parents[--parentOffset]);pfree(parents);}/* When wal_level=logical, guarantee that a subtransaction's xid can only* be seen in the WAL stream if its toplevel xid has been logged before.* If necessary we log an xact_assignment record with fewer than* PGPROC_MAX_CACHED_SUBXIDS. Note that it is fine if didLogXid isn't set* for a transaction even though it appears in a WAL record, we just might* superfluously log something. That can happen when an xid is included* somewhere inside a wal record, but not in XLogRecord->xl_xid, like in* xl_standby_locks. */if (isSubXact && XLogLogicalInfoActive() && !TopTransactionStateData.didLogXid)log_unknown_top = true;

产生一个新的FullTransactionId,并将其记录到PG_PROC和pg_subtrans中。

	/* Generate a new FullTransactionId and record its xid in PG_PROC and pg_subtrans.* NB: we must make the subtrans entry BEFORE the Xid appears anywhere in* shared storage other than PG_PROC; because if there's no room for it in* PG_PROC, the subtrans entry is needed to ensure that other backends see* the Xid as "running".  See GetNewTransactionId. */s->fullTransactionId = GetNewTransactionId(isSubXact);if (!isSubXact) XactTopFullTransactionId = s->fullTransactionId;if (isSubXact)SubTransSetParent(XidFromFullTransactionId(s->fullTransactionId),XidFromFullTransactionId(s->parent->fullTransactionId));/* If it's a top-level transaction, the predicate locking system needs to be told about it too. */if (!isSubXact)RegisterPredicateLockingXid(XidFromFullTransactionId(s->fullTransactionId));

和资源管理器处理相关的逻辑

	/* Acquire lock on the transaction XID.  (We assume this cannot block.) We have to ensure that the lock is assigned to the transaction's own ResourceOwner. */currentOwner = CurrentResourceOwner;CurrentResourceOwner = s->curTransactionOwner;XactLockTableInsert(XidFromFullTransactionId(s->fullTransactionId));CurrentResourceOwner = currentOwner;
	/** Every PGPROC_MAX_CACHED_SUBXIDS assigned transaction ids within each* top-level transaction we issue a WAL record for the assignment. We* include the top-level xid and all the subxids that have not yet been* reported using XLOG_XACT_ASSIGNMENT records.** This is required to limit the amount of shared memory required in a hot* standby server to keep track of in-progress XIDs. See notes for* RecordKnownAssignedTransactionIds().** We don't keep track of the immediate parent of each subxid, only the* top-level transaction that each subxact belongs to. This is correct in* recovery only because aborted subtransactions are separately WAL* logged.* This is correct even for the case where several levels above us didn't* have an xid assigned as we recursed up to them beforehand.*/if (isSubXact && XLogStandbyInfoActive()) {unreportedXids[nUnreportedXids] = XidFromFullTransactionId(s->fullTransactionId);nUnreportedXids++;/* ensure this test matches similar one in RecoverPreparedTransactions() */if (nUnreportedXids >= PGPROC_MAX_CACHED_SUBXIDS || log_unknown_top) {xl_xact_assignment xlrec;/* xtop is always set by now because we recurse up transaction stack to the highest unassigned xid and then come back down */xlrec.xtop = GetTopTransactionId();Assert(TransactionIdIsValid(xlrec.xtop));xlrec.nsubxacts = nUnreportedXids;XLogBeginInsert();XLogRegisterData((char *) &xlrec, MinSizeOfXactAssignment);XLogRegisterData((char *) unreportedXids,nUnreportedXids * sizeof(TransactionId));(void) XLogInsert(RM_XACT_ID, XLOG_XACT_ASSIGNMENT);nUnreportedXids = 0;/* mark top, not current xact as having been logged */TopTransactionStateData.didLogXid = true;}}
}

调用者

GetTopTransactionId函数返回main事务的XID(TopTransactionStateData中的XID)
GetCurrentTransactionId返回当前事务的XID(CurrentTransactionState中的XID)
GetTopFullTransactionId函数返回main事务的XID(TopTransactionStateData中的FullTransactionId)
GetCurrentTransactionId返回当前事务的XID(CurrentTransactionState中的FullTransactionId)

TransactionId GetTopTransactionId(void)
TransactionId GetCurrentTransactionId(void)
FullTransactionId GetTopFullTransactionId(void)
FullTransactionId GetCurrentFullTransactionId(void)

http://www.lryc.cn/news/2418889.html

相关文章:

  • Delphi各个版本的官方下载地址
  • 设计师创业的几种低成本思路
  • “lnk是什么文件 编程“ -> “在编程中,lnk文件的作用和特点“
  • (6)脱壳
  • 朋友圈(拉姆齐定理)- HDU 6152
  • ***工具大全
  • Verilog复杂逻辑设计指南-奇偶校验生成器和校验器及筒式移位器
  • 太吾绘卷第一世攻略_中国文学史上的各种类别的“第一”(史书类)
  • MyEclipse6.5下载地址(含注册码)
  • 论通才与专才
  • 同一Linux下安装两个版本的MySQL(转载)
  • 如何删除带有密码的赛门铁克企业版客户端?
  • Android下nativenbsp;code(C++)的编…
  • OpenHarmony(鸿蒙南向)——平台驱动开发【MMC】
  • Linux下more命令C语言实现实践
  • 如何刻录光盘镜像文件?
  • 基于HTML+CSS+JavaScript仿淘宝购物商城设计毕业论文源码
  • 电脑速记技术考证
  • 经典shell运维实用脚本(非常详细)零基础入门到精通,收藏这一篇就够了
  • 马云经典语录
  • 夏季网吧可以选择什么降温设备来降温
  • Apache虚拟主机配置详细教程(2)
  • 【每天学习一点新知识】带你读懂TCP三次握手和四次挥手
  • Android 安卓 ViewPager中使用Gallery!
  • C语言从入门到放弃
  • 基于Verilog的十字路口交通灯控制电路设计
  • 诺基亚n1平板电脑刷机教程_诺基亚N1 完整包线刷升级或救砖教程(不分台版;国行)...
  • UWB的定位算法(简单详细易懂)
  • java 文件锁 文件序列化 多进程并发处理 工具类
  • 为什么我的xp系统在有进程cidaemon.exe启动时,内存的使用量就一直上升?