这篇文章主要介绍“PostgreSQL中函数CommitTransaction的实现逻辑是什么”,在日常操作中,相信很多人在PostgreSQL中函数CommitTransaction的实现逻辑是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”PostgreSQL中函数CommitTransaction的实现逻辑是什么”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
一、数据结构
TransactionState
事务状态结构体
typedef enum TransState
{
TRANS_DEFAULT,
TRANS_START,
TRANS_INPROGRESS,
TRANS_COMMIT,
TRANS_ABORT,
TRANS_PREPARE
} TransState;
typedef enum TBlockState
{
TBLOCK_DEFAULT,
TBLOCK_STARTED,
TBLOCK_BEGIN,
TBLOCK_INPROGRESS,
TBLOCK_IMPLICIT_INPROGRESS,
TBLOCK_PARALLEL_INPROGRESS,
TBLOCK_END,
TBLOCK_ABORT,
TBLOCK_ABORT_END,
TBLOCK_ABORT_PENDING,
TBLOCK_PREPARE,
TBLOCK_SUBBEGIN,
TBLOCK_SUBINPROGRESS,
TBLOCK_SUBRELEASE,
TBLOCK_SUBCOMMIT,
TBLOCK_SUBABORT,
TBLOCK_SUBABORT_END,
TBLOCK_SUBABORT_PENDING,
TBLOCK_SUBRESTART,
TBLOCK_SUBABORT_RESTART
} TBlockState;
typedef struct TransactionStateData
{
//事务ID
TransactionId transactionId;
//子事务ID
SubTransactionId subTransactionId;
//保存点名称
char *name;
//保存点级别
int savepointLevel;
//低级别的事务状态
TransState state;
//高级别的事务状态
TBlockState blockState;
//事务嵌套深度
int nestingLevel;
//GUC上下文嵌套深度
int gucNestLevel;
//事务生命周期上下文
MemoryContext curTransactionContext;
//查询资源
ResourceOwner curTransactionOwner;
//按XID顺序保存的已提交的子事务ID
TransactionId *childXids;
//childXids数组大小
int nChildXids;
//分配的childXids数组空间
int maxChildXids;
//上一个CurrentUserId
Oid prevUser;
//上一个SecurityRestrictionContext
int prevSecContext;
//上一事务是否只读?
bool prevXactReadOnly;
//是否处于Recovery?
bool startedInRecovery;
//XID是否已保存在WAL Record中?
bool didLogXid;
//Enter/ExitParallelMode计数器
int parallelModeLevel;
//父事务状态
struct TransactionStateData *parent;
} TransactionStateData;
//结构体指针
typedef TransactionStateData *TransactionState;
二、源码解读
CommitTransaction函数,提交事务,并执行相关的清理操作.
static void
CommitTransaction(void)
{
TransactionState s = CurrentTransactionState;
TransactionId latestXid;
bool is_parallel_worker;
is_parallel_worker = (s->blockState == TBLOCK_PARALLEL_INPROGRESS);
//如为并行worker,强制进入并行模式
if (is_parallel_worker)
EnterParallelMode();
ShowTransactionState("CommitTransaction");
if (s->state != TRANS_INPROGRESS)
elog(WARNING, "CommitTransaction while in %s state",
TransStateAsString(s->state));
Assert(s->parent == NULL);
for (;;)
{
AfterTriggerFireDeferred();
if (!PreCommit_Portals(false))
break;
}
CallXactCallbacks(is_parallel_worker ? XACT_EVENT_PARALLEL_PRE_COMMIT
: XACT_EVENT_PRE_COMMIT);
//存在并行worker,清除之
if (IsInParallelMode())
AtEOXact_Parallel(true);
//关闭延迟触发器管理器
AfterTriggerEndXact(true);
PreCommit_on_commit_actions();
//在低级别的清理请,关闭大对象
AtEOXact_LargeObject(true);
PreCommit_CheckForSerializationFailure();
PreCommit_Notify();
//在清理时禁用中断
HOLD_INTERRUPTS();
//提交更新到relation map -- 尽可能晚的执行该动作
AtEOXact_RelationMap(true, is_parallel_worker);
s->state = TRANS_COMMIT;
s->parallelModeLevel = 0;
if (!is_parallel_worker)
{
latestXid = RecordTransactionCommit();
}
else
{
latestXid = InvalidTransactionId;
ParallelWorkerReportLastRecEnd(XactLastRecEnd);
}
TRACE_POSTGRESQL_TRANSACTION_COMMIT(MyProc->lxid);
ProcArrayEndTransaction(MyProc, latestXid);
CallXactCallbacks(is_parallel_worker ? XACT_EVENT_PARALLEL_COMMIT
: XACT_EVENT_COMMIT);
ResourceOwnerRelease(TopTransactionResourceOwner,
RESOURCE_RELEASE_BEFORE_LOCKS,
true, true);
//检查已释放所有的buffer pins
AtEOXact_Buffers(true);
//清理关系缓存
AtEOXact_RelationCache(true);
AtEOXact_Inval(true);
AtEOXact_MultiXact();
ResourceOwnerRelease(TopTransactionResourceOwner,
RESOURCE_RELEASE_LOCKS,
true, true);
ResourceOwnerRelease(TopTransactionResourceOwner,
RESOURCE_RELEASE_AFTER_LOCKS,
true, true);
smgrDoPendingDeletes(true);
AtCommit_Notify();
AtEOXact_GUC(true, 1);
AtEOXact_SPI(true);
AtEOXact_Enum();
AtEOXact_on_commit_actions(true);
AtEOXact_Namespace(true, is_parallel_worker);
AtEOXact_SMgr();
AtEOXact_Files(true);
AtEOXact_ComboCid();
AtEOXact_HashTables(true);
AtEOXact_PgStat(true);
AtEOXact_Snapshot(true, false);
AtEOXact_ApplyLauncher(true);
pgstat_report_xact_timestamp(0);
CurrentResourceOwner = NULL;
ResourceOwnerDelete(TopTransactionResourceOwner);
s->curTransactionOwner = NULL;
CurTransactionResourceOwner = NULL;
TopTransactionResourceOwner = NULL;
AtCommit_Memory();
s->transactionId = InvalidTransactionId;
s->subTransactionId = InvalidSubTransactionId;
s->nestingLevel = 0;
s->gucNestLevel = 0;
s->childXids = NULL;
s->nChildXids = 0;
s->maxChildXids = 0;
XactTopTransactionId = InvalidTransactionId;
nParallelCurrentXids = 0;
s->state = TRANS_DEFAULT;
RESUME_INTERRUPTS();
}
三、跟踪分析
插入数据,执行commit
10:57:56 (xdb@[local]:5432)testdb=# begin;
BEGIN
10:57:59 (xdb@[local]:5432)testdb=#* insert into t_session1 values(1);
INSERT 0 1
10:58:01 (xdb@[local]:5432)testdb=#* commit;
启动gdb,设置断点
(gdb) b CommitTransaction
Breakpoint 1 at 0x5482ae: file xact.c, line 1969.
(gdb) c
Continuing.
Breakpoint 1, CommitTransaction () at xact.c:1969
1969 TransactionState s = CurrentTransactionState;
(gdb)
查看调用栈
(gdb) bt
#0 CommitTransaction () at xact.c:1969
#1 0x0000000000549078 in CommitTransactionCommand () at xact.c:2831
#2 0x00000000008c8ea9 in finish_xact_command () at postgres.c:2523
#3 0x00000000008c6b5d in exec_simple_query (query_string=0x2c97ec8 "commit;") at postgres.c:1170
#4 0x00000000008cae70 in PostgresMain (argc=1, argv=0x2cc3dc8, dbname=0x2cc3c30 "testdb", username=0x2c94ba8 "xdb")
at postgres.c:4182
#5 0x000000000082642b in BackendRun (port=0x2cb9c00) at postmaster.c:4361
#6 0x0000000000825b8f in BackendStartup (port=0x2cb9c00) at postmaster.c:4033
#7 0x0000000000821f1c in ServerLoop () at postmaster.c:1706
#8 0x00000000008217b4 in PostmasterMain (argc=1, argv=0x2c92b60) at postmaster.c:1379
#9 0x00000000007488ef in main (argc=1, argv=0x2c92b60) at main.c:228
(gdb)
当前事务信息
(gdb) p *s
$1 = {transactionId = 2410, subTransactionId = 1, name = 0x0, savepointLevel = 0, state = TRANS_INPROGRESS,
blockState = TBLOCK_END, nestingLevel = 1, gucNestLevel = 1, curTransactionContext = 0x2d3cfa0,
curTransactionOwner = 0x2cc5868, childXids = 0x0, nChildXids = 0, maxChildXids = 0, prevUser = 10, prevSecContext = 0,
prevXactReadOnly = false, startedInRecovery = false, didLogXid = true, parallelModeLevel = 0, parent = 0x0}
(gdb)
执行相关判断,执行预处理等
(gdb) n
1976 if (is_parallel_worker)
(gdb)
1979 ShowTransactionState("CommitTransaction");
(gdb)
1984 if (s->state != TRANS_INPROGRESS)
(gdb)
1987 Assert(s->parent == NULL);
(gdb)
2000 AfterTriggerFireDeferred();
(gdb)
2007 if (!PreCommit_Portals(false))
(gdb)
2008 break;
(gdb)
2011 CallXactCallbacks(is_parallel_worker ? XACT_EVENT_PARALLEL_PRE_COMMIT
(gdb)
继续执行预处理
(gdb) n
2022 if (IsInParallelMode())
(gdb)
2026 AfterTriggerEndXact(true);
(gdb)
2032 PreCommit_on_commit_actions();
(gdb)
2035 AtEOXact_LargeObject(true);
(gdb)
(gdb)
2042 PreCommit_CheckForSerializationFailure();
(gdb)
2049 PreCommit_Notify();
(gdb)
2052 HOLD_INTERRUPTS();
(gdb)
2055 AtEOXact_RelationMap(true);
(gdb)
修改事务状态
2061 s->state = TRANS_COMMIT;
(gdb)
2062 s->parallelModeLevel = 0;
(gdb)
执行实际的提交事务操作
(gdb)
2064 if (!is_parallel_worker)
(gdb)
2070 latestXid = RecordTransactionCommit();
(gdb)
2087 TRACE_POSTGRESQL_TRANSACTION_COMMIT(MyProc->lxid);
(gdb)
通知其他进程知道该进程没有进行中的事务。
(gdb)
2094 ProcArrayEndTransaction(MyProc, latestXid);
(gdb)
2112 CallXactCallbacks(is_parallel_worker ? XACT_EVENT_PARALLEL_COMMIT
(gdb)
释放资源
(gdb)
2115 ResourceOwnerRelease(TopTransactionResourceOwner,
(gdb)
2120 AtEOXact_Buffers(true);
(gdb)
2123 AtEOXact_RelationCache(true);
(gdb)
2132 AtEOXact_Inval(true);
(gdb)
2134 AtEOXact_MultiXact();
(gdb)
2136 ResourceOwnerRelease(TopTransactionResourceOwner,
(gdb)
2139 ResourceOwnerRelease(TopTransactionResourceOwner,
执行清理操作
(gdb)
2152 smgrDoPendingDeletes(true);
(gdb)
2154 AtCommit_Notify();
(gdb)
2155 AtEOXact_GUC(true, 1);
(gdb)
2156 AtEOXact_SPI(true);
(gdb)
2157 AtEOXact_on_commit_actions(true);
(gdb)
2158 AtEOXact_Namespace(true, is_parallel_worker);
(gdb)
2159 AtEOXact_SMgr();
(gdb)
2160 AtEOXact_Files(true);
(gdb)
2161 AtEOXact_ComboCid();
(gdb)
2162 AtEOXact_HashTables(true);
(gdb)
2163 AtEOXact_PgStat(true);
(gdb)
2164 AtEOXact_Snapshot(true, false);
(gdb)
2165 AtEOXact_ApplyLauncher(true);
(gdb)
2166 pgstat_report_xact_timestamp(0);
(gdb)
2168 CurrentResourceOwner = NULL;
(gdb)
2169 ResourceOwnerDelete(TopTransactionResourceOwner);
(gdb)
2170 s->curTransactionOwner = NULL;
(gdb)
重置事务状态
(gdb)
2171 CurTransactionResourceOwner = NULL;
(gdb)
2172 TopTransactionResourceOwner = NULL;
(gdb)
2174 AtCommit_Memory();
(gdb)
2176 s->transactionId = InvalidTransactionId;
(gdb)
2177 s->subTransactionId = InvalidSubTransactionId;
(gdb)
2178 s->nestingLevel = 0;
(gdb)
2179 s->gucNestLevel = 0;
(gdb)
2180 s->childXids = NULL;
(gdb)
2181 s->nChildXids = 0;
(gdb)
2182 s->maxChildXids = 0;
(gdb)
2184 XactTopTransactionId = InvalidTransactionId;
(gdb)
2185 nParallelCurrentXids = 0;
(gdb)
2191 s->state = TRANS_DEFAULT;
(gdb)
2193 RESUME_INTERRUPTS();
(gdb)
2194 }
(gdb)
重置后的事务状态
(gdb) p *s
$2 = {transactionId = 0, subTransactionId = 0, name = 0x0, savepointLevel = 0, state = TRANS_DEFAULT,
blockState = TBLOCK_END, nestingLevel = 0, gucNestLevel = 0, curTransactionContext = 0x0, curTransactionOwner = 0x0,
childXids = 0x0, nChildXids = 0, maxChildXids = 0, prevUser = 10, prevSecContext = 0, prevXactReadOnly = false,
startedInRecovery = false, didLogXid = true, parallelModeLevel = 0, parent = 0x0}
(gdb)
执行完毕
(gdb) n
CommitTransactionCommand () at xact.c:2832
2832 s->blockState = TBLOCK_DEFAULT;
(gdb)
到此,关于“PostgreSQL中函数CommitTransaction的实现逻辑是什么”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!