文章详情

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

请输入下面的图形验证码

提交验证

短信预约提醒成功

PostgreSQL中PGPROC数据结构分析

2024-04-02 19:55

关注

本篇内容介绍了“PostgreSQL中PGPROC数据结构分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

一、数据结构

宏定义


#define MAX_BACKENDS    0x3FFFF


typedef struct SHM_QUEUE
{
    struct SHM_QUEUE *prev;
    struct SHM_QUEUE *next;
} SHM_QUEUE;


#define INVALID_PGPROCNO        PG_INT32_MAX

LWLock
lwlock.c外的代码不应直接操作这个结构的内容,但我们必须声明该结构体以便将LWLocks合并到其他数据结构中。


typedef struct LWLock
{
    uint16      tranche;        
    //独占/非独占locker的状态
    pg_atomic_uint32 state;     
    //正在等待的PGPROCs链表
    proclist_head waiters;      
#ifdef LOCK_DEBUG//用于DEBUG
    //waiters的数量
    pg_atomic_uint32 nwaiters;  
    //锁的最后独占者
    struct PGPROC *owner;       
#endif
} LWLock;

PGPROC
每个后台进程在共享内存中都有一个PGPROC结构体.
全局上也存在未使用的PGPROC结构体链表,用于重用以便为新的后台进程进行分配.
该数据结构的作用是:

PostgreSQL backend processes can't see each other's memory directly, nor can the postmaster see into PostgreSQL backend process memory. Yet they need some way to communicate and co-ordinate, and the postmaster needs a way to keep track of them.

简单来说作用是为了进程间协同和通讯以及postmaster的跟踪.


struct PGPROC
{
    
    //proc->links必须是结构体的第一个域(参考ProcSleep,ProcWakeup...等)
    //如进程在链表中,这是链表的链接
    SHM_QUEUE   links;          
    //持有该PGPROC的procglobal链表数组
    PGPROC    **procgloballist; 
    //可以休眠的信号量
    PGSemaphore sem;            
    //状态为:STATUS_WAITING, STATUS_OK or STATUS_ERROR
    int         waitStatus;     
    //进程通用的latch
    Latch       procLatch;      
    //运行中的进程正在执行的最高层的事务本地ID,如无运行则为InvalidLocalTransactionId
    LocalTransactionId lxid;    
    //后台进程的ID,如为虚拟事务则为0
    int         pid;            
    int         pgprocno;

    
    //------------ 这些域在进程正在启动时为0
    //已分配的后台进程的backend ID
    BackendId   backendId;      
    //该进程使用的数据库ID
    Oid         databaseId;     
    //使用该进程的角色ID
    Oid         roleId;         
    //该进程使用的临时schema OID
    Oid         tempNamespaceId;    
    //如后台进程,则为T
    bool        isBackgroundWorker; 

    
    bool        recoveryConflictPending;

    
    //-------------- 进程正在等待的LWLock相关信息
    //等待LW lock,为T
    bool        lwWaiting;      
    //正在等的LWLock锁模式
    uint8       lwWaitMode;     
    //等待链表中的位置
    proclist_node lwWaitLink;   

    
    //-------------- 支持条件变量
    //CV等待链表中的位置
    proclist_node cvWaitLink;   

    
    //-------------- 进程正在等待的锁信息
    
    //如没有在等待,则waitLock和waitProcLock为NULL
    //休眠...等待的锁对象
    LOCK       *waitLock;       
    //等待锁的每个持锁人信息
    PROCLOCK   *waitProcLock;   
    //等待的所类型
    LOCKMODE    waitLockMode;   
    //该进程已持有锁的类型位掩码
    LOCKMASK    heldLocks;      

    
    //--------------------- 
    //等待该LSN或者更高的LSN
    XLogRecPtr  waitLSN;        
    //同步复制的等待状态
    int         syncRepState;   
    //如进程处于syncrep队列中,则该值保存链表链接
    SHM_QUEUE   syncRepLinks;   

    
    SHM_QUEUE   myProcLocks[NUM_LOCK_PARTITIONS];
    //子事务的XIDs
    struct XidCache subxids;    

    
    
    //支持XID分组清除
    //如属于等待XID清理的ProcArray组,则为T
    bool        procArrayGroupMember;
    
    //等待XID清理的下一个ProcArray组编号
    pg_atomic_uint32 procArrayGroupNext;

    
    TransactionId procArrayGroupMemberXid;
    //进程的等待信息
    uint32      wait_event_info;    

    
    //--------------- 支持组事务状态更新
    //clog组成员,则为T
    bool        clogGroupMember;    
    //下一个clog组成员
    pg_atomic_uint32 clogGroupNext; 
    //clog组成员事务ID
    TransactionId clogGroupMemberXid;   
    //clog组成员的事务状态
    XidStatus   clogGroupMemberXidStatus;   
    //属于clog组成员的事务ID的clog page
    int         clogGroupMemberPage;    
    //clog组成员已提交记录的WAL位置
    XLogRecPtr  clogGroupMemberLsn; 

    
    //每一个后台进程一个LWLock.保护下面的域字段(非组字段)
    LWLock      backendLock;

    
    //---------- 锁管理数据,记录该后台进程以最快路径获得的锁
    //每一个fast-path slot的锁模式
    uint64      fpLockBits;     
    //rel oids的slots
    Oid         fpRelId[FP_LOCK_SLOTS_PER_BACKEND]; 
    //是否持有fast-path VXID锁
    bool        fpVXIDLock;     
    //fast-path VXID锁的lxid
    LocalTransactionId fpLocalTransactionId;    

    
    //--------- 支持锁组.
    //          在组leader中使用LockHashPartitionLockByProc获取LWLock保护这些域
    //锁组的leader,如果"我"是其中一员
    PGPROC     *lockGroupLeader;    
    //如果"我"是leader,这是成员的链表
    dlist_head  lockGroupMembers;   
    //成员连接,如果"我"是其中一员
    dlist_node  lockGroupLink;  
};

MyProc
每个进程都有一个全局变量:MyProc

extern PGDLLIMPORT PGPROC *MyProc;
extern PGDLLIMPORT struct PGXACT *MyPgXact;

二、源码解读

N/A

三、跟踪分析

启动两个Session,执行同样的SQL语句:

insert into t_wal_partition(c1,c2,c3) VALUES(0,'HASH0','HAHS0');

Session 1
启动gdb,开启跟踪

(gdb) b XLogInsertRecord
Breakpoint 1 at 0x54d122: file xlog.c, line 970.
(gdb) c
Continuing.

Breakpoint 1, XLogInsertRecord (rdata=0xf9cc70 <hdr_rdt>, fpw_lsn=0, flags=1 '\001') at xlog.c:970
970     XLogCtlInsert *Insert = &XLogCtl->Insert;

查看内存中的数据结构

(gdb) p *MyProc
$3 = {links = {prev = 0x0, next = 0x0}, procgloballist = 0x7fa79c087c98, sem = 0x7fa779fc81b8, waitStatus = 0, procLatch = {
    is_set = 0, is_shared = true, owner_pid = 1398}, lxid = 3, pid = 1398, pgprocno = 99, backendId = 3, 
  databaseId = 16402, roleId = 10, tempNamespaceId = 0, isBackgroundWorker = false, recoveryConflictPending = false, 
  lwWaiting = false, lwWaitMode = 0 '\000', lwWaitLink = {next = 0, prev = 0}, cvWaitLink = {next = 0, prev = 0}, 
  waitLock = 0x0, waitProcLock = 0x0, waitLockMode = 0, heldLocks = 0, waitLSN = 0, syncRepState = 0, syncRepLinks = {
    prev = 0x0, next = 0x0}, myProcLocks = {{prev = 0x7fa79c09c588, next = 0x7fa79c09c588}, {prev = 0x7fa79c09c598, 
      next = 0x7fa79c09c598}, {prev = 0x7fa79c09c5a8, next = 0x7fa79c09c5a8}, {prev = 0x7fa79c09c5b8, 
      next = 0x7fa79c09c5b8}, {prev = 0x7fa79c09c5c8, next = 0x7fa79c09c5c8}, {prev = 0x7fa79c09c5d8, 
      next = 0x7fa79c09c5d8}, {prev = 0x7fa79c09c5e8, next = 0x7fa79c09c5e8}, {prev = 0x7fa79c09c5f8, 
      next = 0x7fa79c09c5f8}, {prev = 0x7fa79c09c608, next = 0x7fa79c09c608}, {prev = 0x7fa79c09c618, 
      next = 0x7fa79c09c618}, {prev = 0x7fa79c09c628, next = 0x7fa79c09c628}, {prev = 0x7fa79c09c638, 
      next = 0x7fa79c09c638}, {prev = 0x7fa79c09c648, next = 0x7fa79c09c648}, {prev = 0x7fa79c09c658, 
      next = 0x7fa79c09c658}, {prev = 0x7fa79c09c668, next = 0x7fa79c09c668}, {prev = 0x7fa79be25e70, 
      next = 0x7fa79be25e70}}, subxids = {xids = {0 <repeats 64 times>}}, procArrayGroupMember = false, 
  procArrayGroupNext = {value = 2147483647}, procArrayGroupMemberXid = 0, wait_event_info = 0, clogGroupMember = false, 
  clogGroupNext = {value = 2147483647}, clogGroupMemberXid = 0, clogGroupMemberXidStatus = 0, clogGroupMemberPage = -1, 
  clogGroupMemberLsn = 0, backendLock = {tranche = 58, state = {value = 536870912}, waiters = {head = 2147483647, 
      tail = 2147483647}}, fpLockBits = 196027139227648, fpRelId = {0, 0, 0, 0, 0, 2679, 2610, 2680, 2611, 17043, 17040, 
    17037, 17034, 17031, 17028, 17025}, fpVXIDLock = true, fpLocalTransactionId = 3, lockGroupLeader = 0x0, 
  lockGroupMembers = {head = {prev = 0x7fa79c09c820, next = 0x7fa79c09c820}}, lockGroupLink = {prev = 0x0, next = 0x0}}

注意:lwWaiting值为false,表示没有在等待LW Lock

Session 2
启动gdb,开启跟踪

(gdb) b heap_insert
Breakpoint 2 at 0x4df4d1: file heapam.c, line 2449.
(gdb) c
Continuing.
^C
Program received signal SIGINT, Interrupt.
0x00007fa7a7ee7a0b in futex_abstimed_wait (cancel=true, private=<optimized out>, abstime=0x0, expected=0, 
    futex=0x7fa779fc8138) at ../nptl/sysdeps/unix/sysv/linux/sem_waitcommon.c:43
43        err = lll_futex_wait (futex, expected, private);

暂无法进入heap_insert
查看内存中的数据结构

(gdb) p *MyProc
$36 = {links = {prev = 0x0, next = 0x0}, procgloballist = 0x7fa79c087c98, sem = 0x7fa779fc8138, waitStatus = 0, 
  procLatch = {is_set = 1, is_shared = true, owner_pid = 1449}, lxid = 13, pid = 1449, pgprocno = 98, backendId = 4, 
  databaseId = 16402, roleId = 10, tempNamespaceId = 0, isBackgroundWorker = false, recoveryConflictPending = false, 
  lwWaiting = true, lwWaitMode = 0 '\000', lwWaitLink = {next = 114, prev = 2147483647}, cvWaitLink = {next = 0, prev = 0}, 
  waitLock = 0x0, waitProcLock = 0x0, waitLockMode = 0, heldLocks = 0, waitLSN = 0, syncRepState = 0, syncRepLinks = {
    prev = 0x0, next = 0x0}, myProcLocks = {{prev = 0x7fa79c09c238, next = 0x7fa79c09c238}, {prev = 0x7fa79c09c248, 
      next = 0x7fa79c09c248}, {prev = 0x7fa79c09c258, next = 0x7fa79c09c258}, {prev = 0x7fa79c09c268, 
      next = 0x7fa79c09c268}, {prev = 0x7fa79c09c278, next = 0x7fa79c09c278}, {prev = 0x7fa79c09c288, 
      next = 0x7fa79c09c288}, {prev = 0x7fa79c09c298, next = 0x7fa79c09c298}, {prev = 0x7fa79c09c2a8, 
      next = 0x7fa79c09c2a8}, {prev = 0x7fa79c09c2b8, next = 0x7fa79c09c2b8}, {prev = 0x7fa79c09c2c8, 
      next = 0x7fa79c09c2c8}, {prev = 0x7fa79c09c2d8, next = 0x7fa79c09c2d8}, {prev = 0x7fa79c09c2e8, 
      next = 0x7fa79c09c2e8}, {prev = 0x7fa79c09c2f8, next = 0x7fa79c09c2f8}, {prev = 0x7fa79c09c308, 
      next = 0x7fa79c09c308}, {prev = 0x7fa79be21870, next = 0x7fa79be21870}, {prev = 0x7fa79c09c328, 
      next = 0x7fa79c09c328}}, subxids = {xids = {0 <repeats 64 times>}}, procArrayGroupMember = false, 
  procArrayGroupNext = {value = 2147483647}, procArrayGroupMemberXid = 0, wait_event_info = 16777270, 
  clogGroupMember = false, clogGroupNext = {value = 2147483647}, clogGroupMemberXid = 0, clogGroupMemberXidStatus = 0, 
  clogGroupMemberPage = -1, clogGroupMemberLsn = 0, backendLock = {tranche = 58, state = {value = 536870912}, waiters = {
      head = 2147483647, tail = 2147483647}}, fpLockBits = 196027139227648, fpRelId = {0, 0, 0, 0, 0, 2655, 2603, 2680, 
    2611, 17043, 17040, 17037, 17034, 17031, 17028, 17025}, fpVXIDLock = true, fpLocalTransactionId = 13, 
  lockGroupLeader = 0x0, lockGroupMembers = {head = {prev = 0x7fa79c09c4d0, next = 0x7fa79c09c4d0}}, lockGroupLink = {
    prev = 0x0, next = 0x0}}

注意:
lwWaiting值为true,正在等待Session 1的LWLock.
lwWaitLink = {next = 114, prev = 2147483647},其中next = 114,这里的114是指全局变量ProcGlobal(类型为PROC_HDR)->allProcs数组下标为114的ITEM.

(gdb) p ProcGlobal->allProcs[114]
$41 = {links = {prev = 0x0, next = 0x0}, procgloballist = 0x0, sem = 0x7fa779fc8938, waitStatus = 0, procLatch = {
    is_set = 0, is_shared = true, owner_pid = 1351}, lxid = 0, pid = 1351, pgprocno = 114, backendId = -1, databaseId = 0, 
  roleId = 0, tempNamespaceId = 0, isBackgroundWorker = false, recoveryConflictPending = false, lwWaiting = true, 
  lwWaitMode = 1 '\001', lwWaitLink = {next = 2147483647, prev = 98}, cvWaitLink = {next = 0, prev = 0}, waitLock = 0x0, 
  waitProcLock = 0x0, waitLockMode = 0, heldLocks = 0, waitLSN = 0, syncRepState = 0, syncRepLinks = {prev = 0x0, 
    next = 0x0}, myProcLocks = {{prev = 0x7fa79c09f738, next = 0x7fa79c09f738}, {prev = 0x7fa79c09f748, 
      next = 0x7fa79c09f748}, {prev = 0x7fa79c09f758, next = 0x7fa79c09f758}, {prev = 0x7fa79c09f768, 
      next = 0x7fa79c09f768}, {prev = 0x7fa79c09f778, next = 0x7fa79c09f778}, {prev = 0x7fa79c09f788, 
      next = 0x7fa79c09f788}, {prev = 0x7fa79c09f798, next = 0x7fa79c09f798}, {prev = 0x7fa79c09f7a8, 
      next = 0x7fa79c09f7a8}, {prev = 0x7fa79c09f7b8, next = 0x7fa79c09f7b8}, {prev = 0x7fa79c09f7c8, 
      next = 0x7fa79c09f7c8}, {prev = 0x7fa79c09f7d8, next = 0x7fa79c09f7d8}, {prev = 0x7fa79c09f7e8, 
      next = 0x7fa79c09f7e8}, {prev = 0x7fa79c09f7f8, next = 0x7fa79c09f7f8}, {prev = 0x7fa79c09f808, 
      next = 0x7fa79c09f808}, {prev = 0x7fa79c09f818, next = 0x7fa79c09f818}, {prev = 0x7fa79c09f828, 
      next = 0x7fa79c09f828}}, subxids = {xids = {0 <repeats 64 times>}}, procArrayGroupMember = false, 
  procArrayGroupNext = {value = 0}, procArrayGroupMemberXid = 0, wait_event_info = 16777270, clogGroupMember = false, 
  clogGroupNext = {value = 0}, clogGroupMemberXid = 0, clogGroupMemberXidStatus = 0, clogGroupMemberPage = 0, 
  clogGroupMemberLsn = 0, backendLock = {tranche = 58, state = {value = 536870912}, waiters = {head = 2147483647, 
      tail = 2147483647}}, fpLockBits = 0, fpRelId = {0 <repeats 16 times>}, fpVXIDLock = false, fpLocalTransactionId = 0, 
  lockGroupLeader = 0x0, lockGroupMembers = {head = {prev = 0x7fa79c09f9d0, next = 0x7fa79c09f9d0}}, lockGroupLink = {
    prev = 0x0, next = 0x0}}

“PostgreSQL中PGPROC数据结构分析”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!

阅读原文内容投诉

免责声明:

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

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

软考中级精品资料免费领

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

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

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

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

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

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

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