文章目录
海山数据库(He3DB)源码详解:CommitTransaction函数
本文介绍了事务提交过程中,具体执行提交任务的CommitTransaction函数详细执行流程。
1. 执行条件
- 当事务处于TRANS_INPROGRESS状态且事务块处于TBLOCK_STRATED或者TBLOCK_END状态下,由CommitTransactionCommand函数调用CommitTransaction函数完成提交事务。
- 在ParallelWorkerMain函数中由EndParallelWorkerTransaction调用。
2. 执行过程
2.1 获取当前节点状态:
获得当前节点变量值CurrentTransactionState,
并创建两个临时变量latestXid和is_parallel_worker。
TransactionState s = CurrentTransactionState;
TransactionId latestXid;
bool is_parallel_worker;
- CurrentTransactionState主要保存了当前事务状态相关的参数,主要是事务状态、事务块状态、XID、保存点、父节点等级等一系列参数。
- latestXid用来传递保存XID值。
- is_parallel_worker主要用于判断当前事务是否使用并行执行(并行执行指的是数据库将某些查询操作分布到多个工作进程中执行,以提高性能)。
2.2 检查当前状态:
检查并行执行模式,检查当前事务状态并判断父节点状态。
/* Enforce parallel mode restrictions during parallel worker commit. */
if (is_parallel_worker)
EnterParallelMode();
ShowTransactionState("CommitTransaction");
/*
* check the current transaction state
*/
if (s->state != TRANS_INPROGRESS)
elog(WARNING, "CommitTransaction while in %s state",
TransStateAsString(s->state));
Assert(s->parent == NULL);
- 如果执行并行执行模式,调用EnterParallelMode函数执行++s->parallelModeLevel。
- 检查当前事务状态,如果不是TRANS_INPROGRESS,则执行elog函数保存并返回主线程PostgreMain,执行Abort过程。
- 断言检查当前父节点状态,出错直接退出(调试用的)。
2.3 预提交处理:
第一、通过死循环处理用户定义的一些延迟触发器和一些portal操作。
for (;;)
{
/*
* Fire all currently pending deferred triggers.
*/
AfterTriggerFireDeferred();
/*
* Close open portals (converting holdable ones into static portals)
* If there weren't any, we are done. otherwise loop back to check
* if they queued deferred triggers. Lather, rinse, repeat.
*/
if (!PreCommit_Portals(false))
break;
}
这里的死循环行为是:因为,事务(增删改)操作完成之后会触发定义的延迟触发器,进行一些其他的行为,而这些其他行为中可能会包括游标的增删改查,导致了一个套娃操作。所以,这里的AfterTriggerFireDeferred函数处理延迟触发器,PreCommit_Portals处理游标,直到触发器处理完且没有游标需要处理,跳出函数。
- 不断调用AfterTriggerFireDeferred函数,在当前事务提交之前调用,执行并处理掉所有待处理的延迟触发器。
- 通过判断PreCommit_Portals函数的执行结果,来选择是否跳出死循环。PreCommit_Portals函数的作用,首先是将本次事务过程中的持久化游标物质化,并关闭游标对应需要的执行器,释放持有的锁;然后关闭本次事务过程中的一些非持久门户(Non-holdable portals),其他事务留存下来的持久性门户(Portals)不做改变。

最低0.47元/天 解锁文章
799

被折叠的 条评论
为什么被折叠?



