PostgreSQL 原始碼解讀(108)- 後臺程式#1(PGPROC資料結構)
PostgreSQL使用程式模式,對於每一個客戶端會Fork一個後臺程式響應客戶端的請求。本節介紹了每個後臺程式在共享記憶體中都存在一個的資料結構: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}}
ProcGlobal下節再行介紹
四、參考資料
What is the role of struct 'PGPROC' in PostgreSQL?
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/6906/viewspace-2374781/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- PostgreSQL 原始碼解讀(114)- 後臺程式#2(checkpointer程式#1)SQL原始碼
- PostgreSQL 原始碼解讀(124)- 後臺程式#4(autovacuum程式#1)SQL原始碼
- PostgreSQL 原始碼解讀(153)- 後臺程式#5(walsender#1)SQL原始碼
- PostgreSQL 原始碼解讀(192)- 查詢#108(排序#1 - ExecInitSort)SQL原始碼排序
- PostgreSQL 原始碼解讀(1)- 插入資料#1SQL原始碼
- PostgreSQL 原始碼解讀(115)- 後臺程式#3(checkpointer程式#2)SQL原始碼
- PostgreSQL 原始碼解讀(236)- 後臺程式#14(autovacuum程式#2)SQL原始碼
- PostgreSQL 原始碼解讀(205)- 查詢#118(資料結構RangeTblEntry)SQL原始碼資料結構
- PostgreSQL 原始碼解讀(112)- WAL#8(XLogCtrl資料結構)SQL原始碼GC資料結構
- PostgreSQL 原始碼解讀(154)- 後臺程式#6(walsender#2)SQL原始碼
- PostgreSQL 原始碼解讀(213)- 後臺程式#12(checkpointer-CheckpointWriteDelay)SQL原始碼
- PostgreSQL 原始碼解讀(214)- 後臺程式#13(checkpointer-IsCheckpointOnSchedule)SQL原始碼
- PostgreSQL 原始碼解讀(212)- 後臺程式#11(checkpointer-SyncOneBuffer)SQL原始碼
- PostgreSQL 原始碼解讀(211)- 後臺程式#10(checkpointer-BufferSync)SQL原始碼
- PostgreSQL 原始碼解讀(156)- 後臺程式#8(walsender#4)SQL原始碼
- PostgreSQL 原始碼解讀(155)- 後臺程式#7(walsender#3)SQL原始碼
- PostgreSQL 原始碼解讀(109)- WAL#5(相關資料結構)SQL原始碼資料結構
- PostgreSQL 原始碼解讀(206)- 查詢#119(資料結構RangSubselect等)SQL原始碼資料結構
- PostgreSQL 原始碼解讀(178)- 查詢#95(聚合函式)#1相關資料結構SQL原始碼函式資料結構
- PostgreSQL 原始碼解讀(237)- 後臺程式#15(rebuild_database_list)SQL原始碼RebuildDatabase
- PostgreSQL 原始碼解讀(204)- 查詢#117(資料結構SelectStmt&Value)SQL原始碼資料結構
- PostgreSQL 原始碼解讀(207)- 查詢#120(資料結構FromExpr&JoinExpr)SQL原始碼資料結構
- PostgreSQL 原始碼解讀(92)- 分割槽表#1(資料插入路由#1)SQL原始碼路由
- PostgreSQL 原始碼解讀(2)- 插入資料#2(RelationPutHeapTuple)SQL原始碼APT
- PostgreSQL 原始碼解讀(5)- 插入資料#4(ExecInsert)SQL原始碼
- PostgreSQL 原始碼解讀(6)- 插入資料#5(ExecModifyTable)SQL原始碼
- PostgreSQL 原始碼解讀(8)- 插入資料#7(ExecutePlan)SQL原始碼
- PostgreSQL 原始碼解讀(10)- 插入資料#9(ProcessQuery)SQL原始碼
- PostgreSQL 原始碼解讀(13)- 插入資料#12(PostgresMain)SQL原始碼AI
- PostgreSQL 原始碼解讀(157)- 後臺程式#9(同步複製主庫掛起分析)SQL原始碼
- PostgreSQL 原始碼解讀(44)- 查詢語句#29(等價類相關資料結構)SQL原始碼資料結構
- PostgreSQL 原始碼解讀(3)- 如何閱讀原始碼SQL原始碼
- 比特幣原始碼研讀(1)bitcoin原始碼結構比特幣原始碼
- PostgreSQL 原始碼解讀(145)- Storage Manager#1(RecordAndGetPageWithFreeSpace)SQL原始碼
- PostgreSQL 原始碼解讀(116)- MVCC#1(獲取快照#1)SQL原始碼MVCC#
- PostgreSQL 原始碼解讀(4)- 插入資料#3(heap_insert)SQL原始碼
- PostgreSQL:原始碼目錄結構SQL原始碼
- PostgreSQL 原始碼解讀(12)- 插入資料#11(exec_simple_query)SQL原始碼