iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >PostgreSQL中函数StartTransaction的实现逻辑是什么
  • 883
分享到

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

2024-04-02 19:04:59 883人浏览 安东尼
摘要

这篇文章主要讲解了“postgresql中函数StartTransaction的实现逻辑是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Postgres

这篇文章主要讲解了“postgresql中函数StartTransaction的实现逻辑是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Postgresql中函数StartTransaction的实现逻辑是什么”吧!

一、数据结构

静态变量
当前事务状态CurrentTransactionState


static TransactionStateData TopTransactionStateData = {
    .state = TRANS_DEFAULT,
    .blockState = TBLOCK_DEFAULT,
};

static int  nUnreportedXids;
static TransactionId unreportedXids[PGPROC_MAX_CACHED_SUBXIDS];
static TransactionState CurrentTransactionState = &TopTransactionStateData;

static SubTransactionId currentSubTransactionId;
static CommandId currentCommandId;
static bool currentCommandIdUsed;

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;

VirtualTransactionId
VirtualTransactionIDs由执行事务的后台进程BackendId和逻辑分配的LocalTransactionId组成.


typedef struct
{
    BackendId   backendId;      
    LocalTransactionId localTransactionId;  
} VirtualTransactionId;

二、源码解读

StartTransaction函数,用于启动事务,设置事务状态为TRANS_INPROGRESS,CurrentTransactionState->state = TRANS_INPROGRESS.


static void
StartTransaction(void)
{
    TransactionState s;//事务状态
    VirtualTransactionId vxid;//虚拟事务ID
    
    s = &TopTransactionStateData;
    CurrentTransactionState = s;
    Assert(XactTopTransactionId == InvalidTransactionId);
    
    //检查当前事务状态
    Assert(s->state == TRANS_DEFAULT);
    
    s->state = TRANS_START;
    //无效事务ID,待分配
    s->transactionId = InvalidTransactionId;    
    
    s->nestingLevel = 1;
    s->gucNestLevel = 1;
    s->childXids = NULL;
    s->nChildXids = 0;
    s->maxChildXids = 0;
    
    GetUserIdAndSecContext(&s->prevUser, &s->prevSecContext);
    
    //SecurityRestrictionContext不应在事务外设置
    Assert(s->prevSecContext == 0);
    
    if (RecoveryInProgress())
    {
        //只读状态
        s->startedInRecovery = true;
        XactReadOnly = true;
    }
    else
    {
        s->startedInRecovery = false;
        XactReadOnly = DefaultXactReadOnly;
    }
    XactDeferrable = DefaultXactDeferrable;
    XactIsoLevel = DefaultXactIsoLevel;
    forceSyncCommit = false;
    MyXactFlags = 0;
    
    s->subTransactionId = TopSubTransactionId;
    currentSubTransactionId = TopSubTransactionId;
    currentCommandId = FirstCommandId;
    currentCommandIdUsed = false;
    
    nUnreportedXids = 0;
    s->didLogXid = false;
    
    AtStart_Memory();
    AtStart_ResourceOwner();
    
    vxid.backendId = MyBackendId;
    vxid.localTransactionId = GetNextLocalTransactionId();
    
    VirtualXactLockTableInsert(vxid);
    
    Assert(MyProc->backendId == vxid.backendId);
    MyProc->lxid = vxid.localTransactionId;
    TRACE_POSTGRESQL_TRANSACTION_START(vxid.localTransactionId);
    
    if (!IsParallelWorker())
    {
        if (!SPI_inside_nonatomic_context())
            xactStartTimestamp = stmtStartTimestamp;
        else
            xactStartTimestamp = GetCurrentTimestamp();
    }
    else
        Assert(xactStartTimestamp != 0);
    pgstat_report_xact_timestamp(xactStartTimestamp);
    
    //标记xactStopTimestamp未设置
    xactStopTimestamp = 0;
    
    AtStart_GUC();
    AtStart_Cache();
    AfterTriggerBeginXact();
    
    s->state = TRANS_INPROGRESS;
    ShowTransactionState("StartTransaction");
}

三、跟踪分析

执行begin,触发该函数调用

11:10:36 (xdb@[local]:5432)testdb=# begin;

启动gdb,设置断点

(gdb) b StartTransaction
Breakpoint 4 at 0x54800f: file xact.c, line 1825.
(gdb) c
Continuing.
Breakpoint 4, StartTransaction () at xact.c:1825
1825        s = &TopTransactionStateData;
(gdb)

查看调用栈

(gdb) bt
#0  StartTransaction () at xact.c:1825
#1  0x0000000000548f50 in StartTransactionCommand () at xact.c:2718
#2  0x00000000008c8e7d in start_xact_command () at postgres.c:2500
#3  0x00000000008c6771 in exec_simple_query (query_string=0x24a6ec8 "begin;") at postgres.c:948
#4  0x00000000008cae70 in PostgresMain (arGC=1, argv=0x24d2dc8, dbname=0x24d2c30 "testdb", username=0x24a3ba8 "xdb")
    at postgres.c:4182
#5  0x000000000082642b in BackendRun (port=0x24c8c00) at postmaster.c:4361
#6  0x0000000000825b8f in BackendStartup (port=0x24c8c00) at postmaster.c:4033
#7  0x0000000000821f1c in ServerLoop () at postmaster.c:1706
#8  0x00000000008217b4 in PostmasterMain (argc=1, argv=0x24a1b60) at postmaster.c:1379
#9  0x00000000007488ef in main (argc=1, argv=0x24a1b60) at main.c:228
(gdb)

查看TopTransactionStateData全局变量(尚未初始化)

(gdb) p TopTransactionStateData
$7 = {transactionId = 0, subTransactionId = 0, name = 0x0, savepointLevel = 0, state = TRANS_DEFAULT, 
  blockState = TBLOCK_DEFAULT, 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}

设置全局变量CurrentTransactionState = & TopTransactionStateData;

(gdb) n
1826        CurrentTransactionState = s;
(gdb) 
1828        Assert(XactTopTransactionId == InvalidTransactionId);
(gdb)

初始化事务状态

(gdb) n
1833        if (s->state != TRANS_DEFAULT)
(gdb) 
1841        s->state = TRANS_START;
(gdb) 
1842        s->transactionId = InvalidTransactionId;    
(gdb) 
1852        if (RecoveryInProgress())
(gdb) 
1859            s->startedInRecovery = false;
(gdb) 
1860            XactReadOnly = DefaultXactReadOnly;
(gdb) 
1862        XactDeferrable = DefaultXactDeferrable;
(gdb) 
1863        XactIsoLevel = DefaultXactIsoLevel;
(gdb) 
1864        forceSyncCommit = false;
(gdb) 
1865        MyXactFlags = 0;
(gdb) 
1870        s->subTransactionId = TopSubTransactionId;
(gdb) 
1871        currentSubTransactionId = TopSubTransactionId;
(gdb) 
1872        currentCommandId = FirstCommandId;
(gdb) 
1873        currentCommandIdUsed = false;
(gdb) 
1878        nUnreportedXids = 0;
(gdb) 
1879        s->didLogXid = false;
(gdb) 
1884        AtStart_Memory();
(gdb)

启动subsystem(内存/GUC/Cache等)

(gdb) 
1884        AtStart_Memory();
(gdb) n
1885        AtStart_ResourceOwner();
(gdb)

设置虚拟事务ID

1891        vxid.backendId = MyBackendId;
(gdb) 
1892        vxid.localTransactionId = GetNextLocalTransactionId();
(gdb) 
1897        VirtualXactLockTableInsert(vxid);
(gdb) 
1903        Assert(MyProc->backendId == vxid.backendId);
(gdb) p vxid
$8 = {backendId = 3, localTransactionId = 6}
(gdb) 
(gdb) n
1904        MyProc->lxid = vxid.localTransactionId;
(gdb)

设置时间戳

1906        TRACE_POSTGRESQL_TRANSACTION_START(vxid.localTransactionId);
(gdb) 
1917        if (!IsParallelWorker())
(gdb) 
1919            if (!SPI_inside_nonatomic_context())
(gdb) 
1920                xactStartTimestamp = stmtStartTimestamp;
(gdb) 
1926        pgstat_report_xact_timestamp(xactStartTimestamp);
(gdb) 
1928        xactStopTimestamp = 0;
(gdb) 
(gdb) p xactStartTimestamp
$9 = 601009839154257

初始化其他字段

(gdb) n
1935        s->nestingLevel = 1;
(gdb) n
1936        s->gucNestLevel = 1;
(gdb) 
1937        s->childXids = NULL;
(gdb) 
1938        s->nChildXids = 0;
(gdb) 
1939        s->maxChildXids = 0;
(gdb) 
1940        GetUserIdAndSecContext(&s->prevUser, &s->prevSecContext);
(gdb) 
1942        Assert(s->prevSecContext == 0);
(gdb) 
1947        AtStart_GUC();
(gdb) 
1948        AtStart_Cache();
(gdb) 
1949        AfterTriggerBeginXact();
(gdb) 
1955        s->state = TRANS_INPROGRESS;
(gdb) 
1957        ShowTransactionState("StartTransaction");
(gdb) 
1958    }
(gdb)

初始化后的事务状态

(gdb) p *s
$10 = {transactionId = 0, subTransactionId = 1, name = 0x0, savepointLevel = 0, state = TRANS_INPROGRESS, 
  blockState = TBLOCK_DEFAULT, nestingLevel = 1, gucNestLevel = 1, curTransactionContext = 0x2523850, 
  curTransactionOwner = 0x24d4868, childXids = 0x0, nChildXids = 0, maxChildXids = 0, prevUser = 10, prevSecContext = 0, 
  prevXactReadOnly = false, startedInRecovery = false, didLogXid = false, parallelModeLevel = 0, parent = 0x0}
(gdb)

完成调用

(gdb) n
StartTransactionCommand () at xact.c:2719
2719                s->blockState = TBLOCK_STARTED;
(gdb) 
2720                break;
(gdb)

感谢各位的阅读,以上就是“PostgreSQL中函数StartTransaction的实现逻辑是什么”的内容了,经过本文的学习后,相信大家对PostgreSQL中函数StartTransaction的实现逻辑是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

您可能感兴趣的文档:

--结束END--

本文标题: PostgreSQL中函数StartTransaction的实现逻辑是什么

本文链接: https://www.lsjlt.com/news/64851.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作