文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

PostgreSQL中函数CommitTransaction的实现逻辑是什么

2024-04-02 19:55

关注

这篇文章主要介绍“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的实现逻辑是什么”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯