您好,登錄后才能下訂單哦!
本篇內容介紹了“PostgreSQL中PGPROC數據結構分析”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
宏定義
/* * Note: MAX_BACKENDS is limited to 2^18-1 because that's the width reserved * for buffer references in buf_internals.h. This limitation could be lifted * by using a 64bit state; but it's unlikely to be worthwhile as 2^18-1 * backends exceed currently realistic configurations. Even if that limitation * were removed, we still could not a) exceed 2^23-1 because inval.c stores * the backend ID as a 3-byte signed integer, b) INT_MAX/4 because some places * compute 4*MaxBackends without any overflow check. This is rechecked in the * relevant GUC check hooks and in RegisterBackgroundWorker(). * 注意:MAX_BACKENDS限制為2^18-1, * 這是因為該值為buf_internals.h中定義的緩存依賴的最大寬度. * 該限制可以通過使用64bit的狀態來提升,但它看起來并不值當. * 如果去掉該限制,我們仍然不能夠超過: * a) 2^23-1,因為inval.c使用3個字節的有符號整數存儲后臺進程ID * b) INT_MAX/4 ,因為某些地方沒有任何的溢出檢查,直接計算4*MaxBackends的值. * 該值會在相關的GUC檢查鉤子和RegisterBackgroundWorker()函數中檢查. */ #define MAX_BACKENDS 0x3FFFF /* shmqueue.c */ typedef struct SHM_QUEUE { struct SHM_QUEUE *prev; struct SHM_QUEUE *next; } SHM_QUEUE; /* * An invalid pgprocno. Must be larger than the maximum number of PGPROC * structures we could possibly have. See comments for MAX_BACKENDS. * 無效的pg進程號. * 必須大于我們可能擁有的最大的PGPROC數目. * 詳細解釋見MAX_BACKENDS */ #define INVALID_PGPROCNO PG_INT32_MAX
LWLock
lwlock.c外的代碼不應直接操作這個結構的內容,但我們必須聲明該結構體以便將LWLocks合并到其他數據結構中。
/* * Code outside of lwlock.c should not manipulate the contents of this * structure directly, but we have to declare it here to allow LWLocks to be * incorporated into other data structures. * lwlock.c外的代碼不應直接操作這個結構的內容, * 但我們必須聲明該結構體以便將LWLocks合并到其他數據結構中。 */ typedef struct LWLock { uint16 tranche; /* tranche ID */ //獨占/非獨占locker的狀態 pg_atomic_uint32 state; /* state of exclusive/nonexclusive lockers */ //正在等待的PGPROCs鏈表 proclist_head waiters; /* list of waiting PGPROCs */ #ifdef LOCK_DEBUG//用于DEBUG //waiters的數量 pg_atomic_uint32 nwaiters; /* number of waiters */ //鎖的最后獨占者 struct PGPROC *owner; /* last exclusive owner of the lock */ #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的跟蹤.
/* * Each backend has a PGPROC struct in shared memory. There is also a list of * currently-unused PGPROC structs that will be reallocated to new backends. * 每個后臺進程在共享內存中都有一個PGPROC結構體. * 存在未使用的PGPROC結構體鏈表,用于為新的后臺進程重新進行分配. * * links: list link for any list the PGPROC is in. When waiting for a lock, * the PGPROC is linked into that lock's waitProcs queue. A recycled PGPROC * is linked into ProcGlobal's freeProcs list. * links: PGPROC所在的鏈表的鏈接. * 在等待鎖時,PGPROC鏈接到該鎖的waiProc隊列中. * 回收的PGPROC鏈接到ProcGlobal的freeProcs鏈表中. * * Note: twophase.c also sets up a dummy PGPROC struct for each currently * prepared transaction. These PGPROCs appear in the ProcArray data structure * so that the prepared transactions appear to be still running and are * correctly shown as holding locks. A prepared transaction PGPROC can be * distinguished from a real one at need by the fact that it has pid == 0. * The semaphore and lock-activity fields in a prepared-xact PGPROC are unused, * but its myProcLocks[] lists are valid. * 注意:twophase.c也會為每一個當前已準備妥當的事務配置一個虛擬的PGPROC結構. * 這些PGPROCs在數組ProcArray數據結構中出現,以便已準備的事務看起來仍在運行, * 并正確的顯示為持有鎖. * 已準備妥當的事務PGPROC與一個真正的PGPROC事實上的區別是pid == 0. * 在prepared-xact PGPROC中的信號量和活動鎖域字段沒有使用,但myProcLocks[]鏈表是有效的. */ struct PGPROC { /* proc->links MUST BE FIRST IN STRUCT (see ProcSleep,ProcWakeup,etc) */ //proc->links必須是結構體的第一個域(參考ProcSleep,ProcWakeup...等) //如進程在鏈表中,這是鏈表的鏈接 SHM_QUEUE links; /* list link if process is in a list */ //持有該PGPROC的procglobal鏈表數組 PGPROC **procgloballist; /* procglobal list that owns this PGPROC */ //可以休眠的信號量 PGSemaphore sem; /* ONE semaphore to sleep on */ //狀態為:STATUS_WAITING, STATUS_OK or STATUS_ERROR int waitStatus; /* STATUS_WAITING, STATUS_OK or STATUS_ERROR */ //進程通用的latch Latch procLatch; /* generic latch for process */ //運行中的進程正在執行的最高層的事務本地ID,如無運行則為InvalidLocalTransactionId LocalTransactionId lxid; /* local id of top-level transaction currently * being executed by this proc, if running; * else InvalidLocalTransactionId */ //后臺進程的ID,如為虛擬事務則為0 int pid; /* Backend's process ID; 0 if prepared xact */ int pgprocno; /* These fields are zero while a backend is still starting up: */ //------------ 這些域在進程正在啟動時為0 //已分配的后臺進程的backend ID BackendId backendId; /* This backend's backend ID (if assigned) */ //該進程使用的數據庫ID Oid databaseId; /* OID of database this backend is using */ //使用該進程的角色ID Oid roleId; /* OID of role using this backend */ //該進程使用的臨時schema OID Oid tempNamespaceId; /* OID of temp schema this backend is * using */ //如后臺進程,則為T bool isBackgroundWorker; /* true if background worker. */ /* * While in hot standby mode, shows that a conflict signal has been sent * for the current transaction. Set/cleared while holding ProcArrayLock, * though not required. Accessed without lock, if needed. * 如在hot standby模式,顯示已為當前事務發送沖突信號. * 盡管不需要,設置/清除持有的ProcArrayLock. * 如需要,則在沒有持有鎖的情況下訪問. */ bool recoveryConflictPending; /* Info about LWLock the process is currently waiting for, if any. */ //-------------- 進程正在等待的LWLock相關信息 //等待LW lock,為T bool lwWaiting; /* true if waiting for an LW lock */ //正在等的LWLock鎖模式 uint8 lwWaitMode; /* lwlock mode being waited for */ //等待鏈表中的位置 proclist_node lwWaitLink; /* position in LW lock wait list */ /* Support for condition variables. */ //-------------- 支持條件變量 //CV等待鏈表中的位置 proclist_node cvWaitLink; /* position in CV wait list */ /* Info about lock the process is currently waiting for, if any. */ //-------------- 進程正在等待的鎖信息 /* waitLock and waitProcLock are NULL if not currently waiting. */ //如沒有在等待,則waitLock和waitProcLock為NULL //休眠...等待的鎖對象 LOCK *waitLock; /* Lock object we're sleeping on ... */ //等待鎖的每個持鎖人信息 PROCLOCK *waitProcLock; /* Per-holder info for awaited lock */ //等待的所類型 LOCKMODE waitLockMode; /* type of lock we're waiting for */ //該進程已持有鎖的類型位掩碼 LOCKMASK heldLocks; /* bitmask for lock types already held on this * lock object by this backend */ /* * Info to allow us to wait for synchronous replication, if needed. * waitLSN is InvalidXLogRecPtr if not waiting; set only by user backend. * syncRepState must not be touched except by owning process or WALSender. * syncRepLinks used only while holding SyncRepLock. * 允許我們等待同步復制的相關信息. * 如無需等待,則waitLSN為InvalidXLogRecPtr;僅允許由用戶后臺設置。 * 除非擁有process或WALSender,否則不能修改syncRepState。 * 僅在持有SyncRepLock時使用的syncrepink。 */ //--------------------- //等待該LSN或者更高的LSN XLogRecPtr waitLSN; /* waiting for this LSN or higher */ //同步復制的等待狀態 int syncRepState; /* wait state for sync rep */ //如進程處于syncrep隊列中,則該值保存鏈表鏈接 SHM_QUEUE syncRepLinks; /* list link if process is in syncrep queue */ /* * All PROCLOCK objects for locks held or awaited by this backend are * linked into one of these lists, according to the partition number of * their lock. * 該后臺進程持有或等待的鎖相關的所有PROCLOCK對象鏈接在這些鏈表的末尾, * 根據棣屬于這些鎖的分區號進行區分. */ SHM_QUEUE myProcLocks[NUM_LOCK_PARTITIONS]; //子事務的XIDs struct XidCache subxids; /* cache for subtransaction XIDs */ /* Support for group XID clearing. */ /* true, if member of ProcArray group waiting for XID clear */ //支持XID分組清除 //如屬于等待XID清理的ProcArray組,則為T bool procArrayGroupMember; /* next ProcArray group member waiting for XID clear */ //等待XID清理的下一個ProcArray組編號 pg_atomic_uint32 procArrayGroupNext; /* * latest transaction id among the transaction's main XID and * subtransactions * 在事務主XID和子事務之間的最后的事務ID */ TransactionId procArrayGroupMemberXid; //進程的等待信息 uint32 wait_event_info; /* proc's wait information */ /* Support for group transaction status update. */ //--------------- 支持組事務狀態更新 //clog組成員,則為T bool clogGroupMember; /* true, if member of clog group */ //下一個clog組成員 pg_atomic_uint32 clogGroupNext; /* next clog group member */ //clog組成員事務ID TransactionId clogGroupMemberXid; /* transaction id of clog group member */ //clog組成員的事務狀態 XidStatus clogGroupMemberXidStatus; /* transaction status of clog * group member */ //屬于clog組成員的事務ID的clog page int clogGroupMemberPage; /* clog page corresponding to * transaction id of clog group member */ //clog組成員已提交記錄的WAL位置 XLogRecPtr clogGroupMemberLsn; /* WAL location of commit record for clog * group member */ /* Per-backend LWLock. Protects fields below (but not group fields). */ //每一個后臺進程一個LWLock.保護下面的域字段(非組字段) LWLock backendLock; /* Lock manager data, recording fast-path locks taken by this backend. */ //---------- 鎖管理數據,記錄該后臺進程以最快路徑獲得的鎖 //每一個fast-path slot的鎖模式 uint64 fpLockBits; /* lock modes held for each fast-path slot */ //rel oids的slots Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]; /* slots for rel oids */ //是否持有fast-path VXID鎖 bool fpVXIDLock; /* are we holding a fast-path VXID lock? */ //fast-path VXID鎖的lxid LocalTransactionId fpLocalTransactionId; /* lxid for fast-path VXID * lock */ /* * Support for lock groups. Use LockHashPartitionLockByProc on the group * leader to get the LWLock protecting these fields. */ //--------- 支持鎖組. // 在組leader中使用LockHashPartitionLockByProc獲取LWLock保護這些域 //鎖組的leader,如果"我"是其中一員 PGPROC *lockGroupLeader; /* lock group leader, if I'm a member */ //如果"我"是leader,這是成員的鏈表 dlist_head lockGroupMembers; /* list of members, if I'm a leader */ //成員連接,如果"我"是其中一員 dlist_node lockGroupLink; /* my member link, if I'm a member */ };
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數據結構分析”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。