本篇內(nèi)容主要講解“PostgreSQL中heap_insert依賴的函數(shù)有哪些”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“PostgreSQL中heap_insert依賴的函數(shù)有哪些”吧!
創(chuàng)新互聯(lián)專注于榮昌企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站開(kāi)發(fā),電子商務(wù)商城網(wǎng)站建設(shè)。榮昌網(wǎng)站建設(shè)公司,為榮昌等地區(qū)提供建站服務(wù)。全流程按需定制開(kāi)發(fā),專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)
靜態(tài)變量
進(jìn)程中全局共享
/* * An array of XLogRecData structs, to hold registered data. * XLogRecData結(jié)構(gòu)體數(shù)組,存儲(chǔ)已注冊(cè)的數(shù)據(jù) */ static XLogRecData *rdatas; //已使用的入口 static int num_rdatas; /* entries currently used */ //已分配的空間大小 static int max_rdatas; /* allocated size */ //是否調(diào)用XLogBeginInsert函數(shù) static bool begininsert_called = false;
registered_buffer
對(duì)于每一個(gè)使用XLogRegisterBuffer注冊(cè)的每個(gè)數(shù)據(jù)塊,填充到registered_buffer結(jié)構(gòu)體中
/* * For each block reference registered with XLogRegisterBuffer, we fill in * a registered_buffer struct. * 對(duì)于每一個(gè)使用XLogRegisterBuffer注冊(cè)的每個(gè)數(shù)據(jù)塊, * 填充到registered_buffer結(jié)構(gòu)體中 */ typedef struct { //slot是否在使用? bool in_use; /* is this slot in use? */ //REGBUF_* 相關(guān)標(biāo)記 uint8 flags; /* REGBUF_* flags */ //定義關(guān)系和數(shù)據(jù)庫(kù)的標(biāo)識(shí)符 RelFileNode rnode; /* identifies the relation and block */ //fork進(jìn)程編號(hào) ForkNumber forkno; //塊編號(hào) BlockNumber block; //頁(yè)內(nèi)容 Page page; /* page content */ //rdata鏈中的數(shù)據(jù)總大小 uint32 rdata_len; /* total length of data in rdata chain */ //使用該數(shù)據(jù)塊注冊(cè)的數(shù)據(jù)鏈頭 XLogRecData *rdata_head; /* head of the chain of data registered with * this block */ //使用該數(shù)據(jù)塊注冊(cè)的數(shù)據(jù)鏈尾 XLogRecData *rdata_tail; /* last entry in the chain, or &rdata_head if * empty */ //臨時(shí)rdatas數(shù)據(jù)引用,用于存儲(chǔ)XLogRecordAssemble()中使用的備份塊數(shù)據(jù) XLogRecData bkp_rdatas[2]; /* temporary rdatas used to hold references to * backup block data in XLogRecordAssemble() */ /* buffer to store a compressed version of backup block image */ //用于存儲(chǔ)壓縮版本的備份塊鏡像的緩存 char compressed_page[PGLZ_MAX_BLCKSZ]; } registered_buffer; //registered_buffer指正 static registered_buffer *registered_buffers; //已分配的大小 static int max_registered_buffers; /* allocated size */ //最大塊號(hào) + 1(當(dāng)前注冊(cè)塊) static int max_registered_block_id = 0; /* highest block_id + 1 currently * registered */
XLogCtlInsert
WAL插入記錄時(shí)使用的共享數(shù)據(jù)結(jié)構(gòu)
/* * Shared state data for WAL insertion. * WAL插入記錄時(shí)使用的共享數(shù)據(jù)結(jié)構(gòu) */ typedef struct XLogCtlInsert { //包含CurrBytePos和PrevBytePos的lock slock_t insertpos_lck; /* protects CurrBytePos and PrevBytePos */ /* * CurrBytePos is the end of reserved WAL. The next record will be * inserted at that position. PrevBytePos is the start position of the * previously inserted (or rather, reserved) record - it is copied to the * prev-link of the next record. These are stored as "usable byte * positions" rather than XLogRecPtrs (see XLogBytePosToRecPtr()). * CurrBytePos是保留WAL的結(jié)束位置。 * 下一條記錄將插入到那個(gè)位置。 * PrevBytePos是先前插入(或者保留)記錄的起始位置——它被復(fù)制到下一條記錄的prev-link中。 * 這些存儲(chǔ)為“可用字節(jié)位置”,而不是XLogRecPtrs(參見(jiàn)XLogBytePosToRecPtr())。 */ uint64 CurrBytePos; uint64 PrevBytePos; /* * Make sure the above heavily-contended spinlock and byte positions are * on their own cache line. In particular, the RedoRecPtr and full page * write variables below should be on a different cache line. They are * read on every WAL insertion, but updated rarely, and we don't want * those reads to steal the cache line containing Curr/PrevBytePos. * 確保以上激烈競(jìng)爭(zhēng)的自旋鎖和字節(jié)位置在它們自己的緩存line上。 * 特別是,RedoRecPtr和下面的全頁(yè)寫(xiě)變量應(yīng)該位于不同的緩存line上。 * 它們?cè)诿看尾迦隬AL時(shí)都被讀取,但很少更新, * 我們不希望這些讀取竊取包含Curr/PrevBytePos的緩存line。 */ char pad[PG_CACHE_LINE_SIZE]; /* * fullPageWrites is the master copy used by all backends to determine * whether to write full-page to WAL, instead of using process-local one. * This is required because, when full_page_writes is changed by SIGHUP, * we must WAL-log it before it actually affects WAL-logging by backends. * Checkpointer sets at startup or after SIGHUP. * fullpagewrite是所有后臺(tái)進(jìn)程使用的主副本, * 用于確定是否將整個(gè)頁(yè)面寫(xiě)入WAL,而不是使用process-local副本。 * 這是必需的,因?yàn)楫?dāng)SIGHUP更改full_page_write時(shí), * 我們必須在它通過(guò)后臺(tái)進(jìn)程實(shí)際影響WAL-logging之前對(duì)其進(jìn)行WAL-log記錄。 * Checkpointer檢查點(diǎn)設(shè)置在啟動(dòng)或SIGHUP之后。 * * To read these fields, you must hold an insertion lock. To modify them, * you must hold ALL the locks. * 為了讀取這些域,必須持有insertion lock. * 如需更新,則需要持有所有這些lock. */ //插入時(shí)的當(dāng)前redo point XLogRecPtr RedoRecPtr; /* current redo point for insertions */ //為PITR強(qiáng)制執(zhí)行full-page寫(xiě)? bool forcePageWrites; /* forcing full-page writes for PITR? */ //是否全頁(yè)寫(xiě)? bool fullPageWrites; /* * exclusiveBackupState indicates the state of an exclusive backup (see * comments of ExclusiveBackupState for more details). nonExclusiveBackups * is a counter indicating the number of streaming base backups currently * in progress. forcePageWrites is set to true when either of these is * non-zero. lastBackupStart is the latest checkpoint redo location used * as a starting point for an online backup. * exclusive sivebackupstate表示排他備份的狀態(tài) * (有關(guān)詳細(xì)信息,請(qǐng)參閱exclusive sivebackupstate的注釋)。 * 非排他性備份是一個(gè)計(jì)數(shù)器,指示當(dāng)前正在進(jìn)行的流基礎(chǔ)備份的數(shù)量。 * forcePageWrites在這兩個(gè)值都不為零時(shí)被設(shè)置為true。 * lastBackupStart用作在線備份起點(diǎn)的最新檢查點(diǎn)的重做位置。 */ ExclusiveBackupState exclusiveBackupState; int nonExclusiveBackups; XLogRecPtr lastBackupStart; /* * WAL insertion locks. * WAL寫(xiě)入鎖 */ WALInsertLockPadded *WALInsertLocks; } XLogCtlInsert;
XLogRecData
xloginsert.c中的函數(shù)構(gòu)造一個(gè)XLogRecData結(jié)構(gòu)體鏈用于標(biāo)識(shí)最后的WAL記錄
/* * The functions in xloginsert.c construct a chain of XLogRecData structs * to represent the final WAL record. * xloginsert.c中的函數(shù)構(gòu)造一個(gè)XLogRecData結(jié)構(gòu)體鏈用于標(biāo)識(shí)最后的WAL記錄 */ typedef struct XLogRecData { //鏈中的下一個(gè)結(jié)構(gòu)體,如無(wú)則為NULL struct XLogRecData *next; /* next struct in chain, or NULL */ //rmgr數(shù)據(jù)的起始地址 char *data; /* start of rmgr data to include */ //rmgr數(shù)據(jù)大小 uint32 len; /* length of rmgr data to include */ } XLogRecData;
registered_buffer/registered_buffers
對(duì)于每一個(gè)使用XLogRegisterBuffer注冊(cè)的每個(gè)數(shù)據(jù)塊,填充到registered_buffer結(jié)構(gòu)體中
/* * For each block reference registered with XLogRegisterBuffer, we fill in * a registered_buffer struct. * 對(duì)于每一個(gè)使用XLogRegisterBuffer注冊(cè)的每個(gè)數(shù)據(jù)塊, * 填充到registered_buffer結(jié)構(gòu)體中 */ typedef struct { //slot是否在使用? bool in_use; /* is this slot in use? */ //REGBUF_* 相關(guān)標(biāo)記 uint8 flags; /* REGBUF_* flags */ //定義關(guān)系和數(shù)據(jù)庫(kù)的標(biāo)識(shí)符 RelFileNode rnode; /* identifies the relation and block */ //fork進(jìn)程編號(hào) ForkNumber forkno; //塊編號(hào) BlockNumber block; //頁(yè)內(nèi)容 Page page; /* page content */ //rdata鏈中的數(shù)據(jù)總大小 uint32 rdata_len; /* total length of data in rdata chain */ //使用該數(shù)據(jù)塊注冊(cè)的數(shù)據(jù)鏈頭 XLogRecData *rdata_head; /* head of the chain of data registered with * this block */ //使用該數(shù)據(jù)塊注冊(cè)的數(shù)據(jù)鏈尾 XLogRecData *rdata_tail; /* last entry in the chain, or &rdata_head if * empty */ //臨時(shí)rdatas數(shù)據(jù)引用,用于存儲(chǔ)XLogRecordAssemble()中使用的備份塊數(shù)據(jù) XLogRecData bkp_rdatas[2]; /* temporary rdatas used to hold references to * backup block data in XLogRecordAssemble() */ /* buffer to store a compressed version of backup block image */ //用于存儲(chǔ)壓縮版本的備份塊鏡像的緩存 char compressed_page[PGLZ_MAX_BLCKSZ]; } registered_buffer; //registered_buffer指針(全局變量) static registered_buffer *registered_buffers; //已分配的大小 static int max_registered_buffers; /* allocated size */ //最大塊號(hào) + 1(當(dāng)前注冊(cè)塊) static int max_registered_block_id = 0; /* highest block_id + 1 currently * registered */
heap_insert
主要實(shí)現(xiàn)邏輯是插入元組到堆中,其中存在對(duì)WAL(XLog)進(jìn)行處理的部分.
參見(jiàn)PostgreSQL 源碼解讀(104)- WAL#1(Insert & WAL-heap_insert函數(shù)#1)
XLogBeginInsert
開(kāi)始構(gòu)造WAL記錄.
必須在調(diào)用XLogRegister*和XLogInsert()函數(shù)前調(diào)用.
/* * Begin constructing a WAL record. This must be called before the * XLogRegister* functions and XLogInsert(). * 開(kāi)始構(gòu)造WAL記錄. * 必須在調(diào)用XLogRegister*和XLogInsert()函數(shù)前調(diào)用. */ void XLogBeginInsert(void) { //驗(yàn)證邏輯 Assert(max_registered_block_id == 0); Assert(mainrdata_last == (XLogRecData *) &mainrdata_head); Assert(mainrdata_len == 0); /* cross-check on whether we should be here or not */ //交叉校驗(yàn)是否應(yīng)該在這里還是不應(yīng)該在這里出現(xiàn) if (!XLogInsertAllowed()) elog(ERROR, "cannot make new WAL entries during recovery"); if (begininsert_called) elog(ERROR, "XLogBeginInsert was already called"); //變量賦值 begininsert_called = true; } /* * Is this process allowed to insert new WAL records? * 判斷該進(jìn)程是否允許插入新的WAL記錄 * * Ordinarily this is essentially equivalent to !RecoveryInProgress(). * But we also have provisions for forcing the result "true" or "false" * within specific processes regardless of the global state. * 通常,這本質(zhì)上等同于! recoverinprogress()。 * 但我們也有規(guī)定,無(wú)論全局狀況如何,都要在特定進(jìn)程中強(qiáng)制實(shí)現(xiàn)“正確”或“錯(cuò)誤”的結(jié)果。 */ bool XLogInsertAllowed(void) { /* * If value is "unconditionally true" or "unconditionally false", just * return it. This provides the normal fast path once recovery is known * done. * 如果值為“無(wú)條件為真”或“無(wú)條件為假”,則返回。 * 這提供正常的快速判斷路徑。 */ if (LocalXLogInsertAllowed >= 0) return (bool) LocalXLogInsertAllowed; /* * Else, must check to see if we're still in recovery. * 否則,必須檢查是否處于恢復(fù)狀態(tài) */ if (RecoveryInProgress()) return false; /* * On exit from recovery, reset to "unconditionally true", since there is * no need to keep checking. * 從恢復(fù)中退出,由于不需要繼續(xù)檢查,重置為"無(wú)條件為真" */ LocalXLogInsertAllowed = 1; return true; }
XLogRegisterData
添加數(shù)據(jù)到正在構(gòu)造的WAL記錄中
/* * Add data to the WAL record that's being constructed. * 添加數(shù)據(jù)到正在構(gòu)造的WAL記錄中 * * The data is appended to the "main chunk", available at replay with * XLogRecGetData(). * 數(shù)據(jù)追加到"main chunk"中,用于XLogRecGetData()函數(shù)回放 */ void XLogRegisterData(char *data, int len) { XLogRecData *rdata;//數(shù)據(jù) //驗(yàn)證是否已調(diào)用begin Assert(begininsert_called); //驗(yàn)證大小 if (num_rdatas >= max_rdatas) elog(ERROR, "too much WAL data"); rdata = &rdatas[num_rdatas++]; rdata->data = data; rdata->len = len; /* * we use the mainrdata_last pointer to track the end of the chain, so no * need to clear 'next' here. * 使用mainrdata_last指針跟蹤鏈條的結(jié)束點(diǎn),在這里不需要清除next變量 */ mainrdata_last->next = rdata; mainrdata_last = rdata; mainrdata_len += len; }
XLogRegisterBuffer
在緩沖區(qū)中注冊(cè)已構(gòu)建的WAL記錄的依賴,在WAL-logged操作更新每一個(gè)page時(shí)必須調(diào)用此函數(shù)
/* * Register a reference to a buffer with the WAL record being constructed. * This must be called for every page that the WAL-logged operation modifies. * 在緩沖區(qū)中注冊(cè)已構(gòu)建的WAL記錄的依賴 * 在WAL-logged操作更新每一個(gè)page時(shí)必須調(diào)用此函數(shù) */ void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags) { registered_buffer *regbuf;//緩沖 /* NO_IMAGE doesn't make sense with FORCE_IMAGE */ //NO_IMAGE不能與REGBUF_NO_IMAGE同時(shí)使用 Assert(!((flags & REGBUF_FORCE_IMAGE) && (flags & (REGBUF_NO_IMAGE)))); Assert(begininsert_called); //塊ID > 最大已注冊(cè)的緩沖區(qū),報(bào)錯(cuò) if (block_id >= max_registered_block_id) { if (block_id >= max_registered_buffers) elog(ERROR, "too many registered buffers"); max_registered_block_id = block_id + 1; } //賦值 regbuf = ®istered_buffers[block_id]; //獲取Tag BufferGetTag(buffer, ®buf->rnode, ®buf->forkno, ®buf->block); regbuf->page = BufferGetPage(buffer); regbuf->flags = flags; regbuf->rdata_tail = (XLogRecData *) ®buf->rdata_head; regbuf->rdata_len = 0; /* * Check that this page hasn't already been registered with some other * block_id. * 檢查該page是否已被其他block_id注冊(cè) */ #ifdef USE_ASSERT_CHECKING { int i; for (i = 0; i < max_registered_block_id; i++)//循環(huán)檢查 { registered_buffer *regbuf_old = ®istered_buffers[i]; if (i == block_id || !regbuf_old->in_use) continue; Assert(!RelFileNodeEquals(regbuf_old->rnode, regbuf->rnode) || regbuf_old->forkno != regbuf->forkno || regbuf_old->block != regbuf->block); } } #endif regbuf->in_use = true;//標(biāo)記為使用 } /* * BufferGetTag * Returns the relfilenode, fork number and block number associated with * a buffer. * 返回與緩沖區(qū)相關(guān)的relfilenode,fork編號(hào)和塊號(hào) */ void BufferGetTag(Buffer buffer, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum) { BufferDesc *bufHdr; /* Do the same checks as BufferGetBlockNumber. */ //驗(yàn)證buffer已被pinned Assert(BufferIsPinned(buffer)); if (BufferIsLocal(buffer)) bufHdr = GetLocalBufferDescriptor(-buffer - 1); else bufHdr = GetBufferDescriptor(buffer - 1); /* pinned, so OK to read tag without spinlock */ //pinned,不需要spinlock讀取tage *rnode = bufHdr->tag.rnode; *forknum = bufHdr->tag.forkNum; *blknum = bufHdr->tag.blockNum; } /* * BufferIsLocal * True iff the buffer is local (not visible to other backends). * 如緩沖區(qū)對(duì)其他后臺(tái)進(jìn)程不不可見(jiàn),則為本地buffer */ #define BufferIsLocal(buffer) ((buffer) < 0) #define GetBufferDescriptor(id) (&BufferDescriptors[(id)].bufferdesc) #define GetLocalBufferDescriptor(id) (&LocalBufferDescriptors[(id)]) BufferDesc *LocalBufferDescriptors = NULL; BufferDescPadded *BufferDescriptors;
XLogRegisterBufData
在正在構(gòu)造的WAL記錄中添加buffer相關(guān)的數(shù)據(jù).
/* * Add buffer-specific data to the WAL record that's being constructed. * 在正在構(gòu)造的WAL記錄中添加buffer相關(guān)的數(shù)據(jù). * * Block_id must reference a block previously registered with * XLogRegisterBuffer(). If this is called more than once for the same * block_id, the data is appended. * Block_id必須引用先前注冊(cè)到XLogRegisterBuffer()中的數(shù)據(jù)塊。 * 如果對(duì)同一個(gè)block_id不止一次調(diào)用,那么數(shù)據(jù)將會(huì)追加。 * * The maximum amount of data that can be registered per block is 65535 * bytes. That should be plenty; if you need more than BLCKSZ bytes to * reconstruct the changes to the page, you might as well just log a full * copy of it. (the "main data" that's not associated with a block is not * limited) * 每個(gè)塊可注冊(cè)的最大大小是65535Bytes. * 通常來(lái)說(shuō)這已經(jīng)足夠了;如果需要大小比BLCKSZ字節(jié)更大的數(shù)據(jù)用于重建頁(yè)面的變化, * 那么需要整頁(yè)進(jìn)行拷貝. * (與數(shù)據(jù)塊相關(guān)的"main data"是不受限的) */ void XLogRegisterBufData(uint8 block_id, char *data, int len) { registered_buffer *regbuf;//注冊(cè)的緩沖區(qū) XLogRecData *rdata;//數(shù)據(jù) Assert(begininsert_called);//XLogBeginInsert函數(shù)已調(diào)用 /* find the registered buffer struct */ //尋找已注冊(cè)的緩存結(jié)構(gòu)體 regbuf = ®istered_buffers[block_id]; if (!regbuf->in_use) elog(ERROR, "no block with id %d registered with WAL insertion", block_id); if (num_rdatas >= max_rdatas) elog(ERROR, "too much WAL data"); rdata = &rdatas[num_rdatas++]; rdata->data = data; rdata->len = len; regbuf->rdata_tail->next = rdata; regbuf->rdata_tail = rdata; regbuf->rdata_len += len; }
XLogSetRecordFlags
為即將"到來(lái)"的WAL記錄設(shè)置插入狀態(tài)標(biāo)記
XLOG_INCLUDE_ORIGIN 確定復(fù)制起點(diǎn)是否應(yīng)該包含在記錄中
XLOG_MARK_UNIMPORTANT 表示記錄對(duì)于持久性并不重要,這可以避免觸發(fā)WAL歸檔和其他后臺(tái)活動(dòng)
/* * Set insert status flags for the upcoming WAL record. * 為即將"到來(lái)"的WAL記錄設(shè)置插入狀態(tài)標(biāo)記 * * The flags that can be used here are: * - XLOG_INCLUDE_ORIGIN, to determine if the replication origin should be * included in the record. * - XLOG_MARK_UNIMPORTANT, to signal that the record is not important for * durability, which allows to avoid triggering WAL archiving and other * background activity. * 標(biāo)記用于: * - XLOG_INCLUDE_ORIGIN 確定復(fù)制起點(diǎn)是否應(yīng)該包含在記錄中 * - XLOG_MARK_UNIMPORTANT 表示記錄對(duì)于持久性并不重要,這可以避免觸發(fā)WAL歸檔和其他后臺(tái)活動(dòng)。 */ void XLogSetRecordFlags(uint8 flags) { Assert(begininsert_called); curinsert_flags = flags; }
測(cè)試腳本如下
insert into t_wal_partition(c1,c2,c3) VALUES(0,'HASH0','HAHS0');
XLogBeginInsert
啟動(dòng)gdb,設(shè)置斷點(diǎn),進(jìn)入XLogBeginInsert
(gdb) b XLogBeginInsert Breakpoint 1 at 0x564897: file xloginsert.c, line 122. (gdb) c Continuing. Breakpoint 1, XLogBeginInsert () at xloginsert.c:122 122 Assert(max_registered_block_id == 0);
校驗(yàn),調(diào)用XLogInsertAllowed
122 Assert(max_registered_block_id == 0); (gdb) n 123 Assert(mainrdata_last == (XLogRecData *) &mainrdata_head); (gdb) 124 Assert(mainrdata_len == 0); (gdb) 127 if (!XLogInsertAllowed()) (gdb) step XLogInsertAllowed () at xlog.c:8126 8126 if (LocalXLogInsertAllowed >= 0) (gdb) n 8132 if (RecoveryInProgress()) (gdb) 8139 LocalXLogInsertAllowed = 1; (gdb) 8140 return true; (gdb) 8141 } (gdb)
賦值,設(shè)置begininsert_called為T(mén),返回
(gdb) XLogBeginInsert () at xloginsert.c:130 130 if (begininsert_called) (gdb) p begininsert_called $1 = false (gdb) n 133 begininsert_called = true; (gdb) 134 } (gdb) heap_insert (relation=0x7f5cc0338228, tup=0x29b2440, cid=0, options=0, bistate=0x0) at heapam.c:2567 2567 XLogRegisterData((char *) &xlrec, SizeOfHeapInsert); (gdb)
XLogRegisterData
進(jìn)入XLogRegisterData函數(shù)
(gdb) step XLogRegisterData (data=0x7fff03ba99e0 "\002", len=3) at xloginsert.c:327 327 Assert(begininsert_called); (gdb) p *data $2 = 2 '\002' (gdb) p *(xl_heap_insert *)data $3 = {offnum = 2, flags = 0 '\000'}
執(zhí)行相關(guān)判斷,并賦值
rdatas是XLogRecData結(jié)構(gòu)體指針,全局靜態(tài)變量:
static XLogRecData *rdatas;
(gdb) n 329 if (num_rdatas >= max_rdatas) (gdb) p num_rdatas $4 = 0 (gdb) p max_rdatas $5 = 20 (gdb) n 331 rdata = &rdatas[num_rdatas++]; (gdb) p rdatas[0] $6 = {next = 0x0, data = 0x0, len = 0} (gdb) p rdatas[1] $7 = {next = 0x0, data = 0x0, len = 0}
相關(guān)結(jié)構(gòu)體賦值
其中mainrdata_last是mainrdata_head的地址:
static XLogRecData *mainrdata_head;
static XLogRecData *mainrdata_last = (XLogRecData *) &mainrdata_head;
(gdb) n 333 rdata->data = data; (gdb) 334 rdata->len = len; (gdb) 341 mainrdata_last->next = rdata; (gdb) 342 mainrdata_last = rdata; (gdb) 344 mainrdata_len += len; (gdb) 345 }
完成調(diào)用,回到heap_insert
(gdb) n heap_insert (relation=0x7f5cc0338228, tup=0x29b2440, cid=0, options=0, bistate=0x0) at heapam.c:2569 2569 xlhdr.t_infomask2 = heaptup->t_data->t_infomask2;
XLogRegisterBuffer
進(jìn)入XLogRegisterBuffer
(gdb) step XLogRegisterBuffer (block_id=0 '\000', buffer=99, flags=8 '\b') at xloginsert.c:218 218 Assert(!((flags & REGBUF_FORCE_IMAGE) && (flags & (REGBUF_NO_IMAGE))));
判斷block_id,設(shè)置max_registered_block_id變量等.
注:max_registered_buffers初始化為5
(gdb) n 219 Assert(begininsert_called); (gdb) 221 if (block_id >= max_registered_block_id) (gdb) p max_registered_block_id $14 = 0 (gdb) n 223 if (block_id >= max_registered_buffers) (gdb) p max_registered_buffers $15 = 5 (gdb) n 225 max_registered_block_id = block_id + 1; (gdb) 228 regbuf = ®istered_buffers[block_id]; (gdb) p max_registered_buffers $16 = 5 (gdb) p max_registered_block_id $17 = 1 (gdb) n 230 BufferGetTag(buffer, ®buf->rnode, ®buf->forkno, ®buf->block); (gdb) p *regbuf $18 = {in_use = false, flags = 0 '\000', rnode = {spcNode = 0, dbNode = 0, relNode = 0}, forkno = MAIN_FORKNUM, block = 0, page = 0x0, rdata_len = 0, rdata_head = 0x0, rdata_tail = 0x0, bkp_rdatas = {{next = 0x0, data = 0x0, len = 0}, { next = 0x0, data = 0x0, len = 0}}, compressed_page = '\000' <repeats 8195 times>}
獲取buffer的tag
rnode/forkno/block
(gdb) n 231 regbuf->page = BufferGetPage(buffer); (gdb) p *regbuf $19 = {in_use = false, flags = 0 '\000', rnode = {spcNode = 1663, dbNode = 16402, relNode = 17034}, forkno = MAIN_FORKNUM, block = 0, page = 0x0, rdata_len = 0, rdata_head = 0x0, rdata_tail = 0x0, bkp_rdatas = {{next = 0x0, data = 0x0, len = 0}, {next = 0x0, data = 0x0, len = 0}}, compressed_page = '\000' <repeats 8195 times>}
設(shè)置flags等其他變量
(gdb) n 232 regbuf->flags = flags; (gdb) 233 regbuf->rdata_tail = (XLogRecData *) ®buf->rdata_head; (gdb) 234 regbuf->rdata_len = 0; (gdb) 244 for (i = 0; i < max_registered_block_id; i++) (gdb) p regbuf->flags $21 = 8 '\b' (gdb) p *regbuf->rdata_tail $23 = {next = 0x0, data = 0x292e1a8 "", len = 0} (gdb) p regbuf->rdata_len $24 = 0
檢查該page是否已被其他block_id注冊(cè)
最后設(shè)置in_use為T(mén),返回XLogRegisterBufData
(gdb) n 246 registered_buffer *regbuf_old = ®istered_buffers[i]; (gdb) 248 if (i == block_id || !regbuf_old->in_use) (gdb) 249 continue; (gdb) 244 for (i = 0; i < max_registered_block_id; i++) (gdb) 258 regbuf->in_use = true; (gdb) 259 } (gdb) heap_insert (relation=0x7f5cc0338228, tup=0x29b2440, cid=0, options=0, bistate=0x0) at heapam.c:2579 2579 XLogRegisterBufData(0, (char *) &xlhdr, SizeOfHeapHeader);
XLogRegisterBufData
進(jìn)入XLogRegisterBufData函數(shù)
(gdb) step XLogRegisterBufData (block_id=0 '\000', data=0x7fff03ba99d0 "\003", len=5) at xloginsert.c:366 366 Assert(begininsert_called);
尋找已注冊(cè)的緩存結(jié)構(gòu)體
(gdb) n 369 regbuf = ®istered_buffers[block_id]; (gdb) 370 if (!regbuf->in_use) (gdb) p *regbuf $25 = {in_use = true, flags = 8 '\b', rnode = {spcNode = 1663, dbNode = 16402, relNode = 17034}, forkno = MAIN_FORKNUM, block = 0, page = 0x7f5c93854380 "\001", rdata_len = 0, rdata_head = 0x0, rdata_tail = 0x292e1a8, bkp_rdatas = {{ next = 0x0, data = 0x0, len = 0}, {next = 0x0, data = 0x0, len = 0}}, compressed_page = '\000' <repeats 8195 times>} (gdb) p *regbuf->page $26 = 1 '\001' (gdb) n 374 if (num_rdatas >= max_rdatas) (gdb)
在正在構(gòu)造的WAL記錄中添加buffer相關(guān)的數(shù)據(jù).
(gdb) n 376 rdata = &rdatas[num_rdatas++]; (gdb) p num_rdatas $27 = 1 (gdb) p max_rdatas $28 = 20 (gdb) n 378 rdata->data = data; (gdb) 379 rdata->len = len; (gdb) 381 regbuf->rdata_tail->next = rdata; (gdb) 382 regbuf->rdata_tail = rdata; (gdb) 383 regbuf->rdata_len += len; (gdb) 384 } (gdb) p *rdata $29 = {next = 0x0, data = 0x7fff03ba99d0 "\003", len = 5} (gdb)
完成調(diào)用,回到heap_insert
(gdb) n heap_insert (relation=0x7f5cc0338228, tup=0x29b2440, cid=0, options=0, bistate=0x0) at heapam.c:2583 2583 heaptup->t_len - SizeofHeapTupleHeader);
繼續(xù)調(diào)用XLogRegisterBufData函數(shù)注冊(cè)tuple實(shí)際數(shù)據(jù)
2583 heaptup->t_len - SizeofHeapTupleHeader); (gdb) n 2581 XLogRegisterBufData(0, (gdb)
XLogSetRecordFlags
為即將"到來(lái)"的WAL記錄設(shè)置插入狀態(tài)標(biāo)記
(gdb) 2586 XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
邏輯很簡(jiǎn)單,設(shè)置標(biāo)記位curinsert_flags
(gdb) step XLogSetRecordFlags (flags=1 '\001') at xloginsert.c:399 399 Assert(begininsert_called); (gdb) n 400 curinsert_flags = flags; (gdb) 401 } (gdb) heap_insert (relation=0x7f5cc0338228, tup=0x29b2440, cid=0, options=0, bistate=0x0) at heapam.c:2588 2588 recptr = XLogInsert(RM_HEAP_ID, info); (gdb)
調(diào)用XLogInsert,插入WAL
(gdb) 2590 PageSetLSN(page, recptr); ...
到此,相信大家對(duì)“PostgreSQL中heap_insert依賴的函數(shù)有哪些”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
網(wǎng)站名稱:PostgreSQL中heap_insert依賴的函數(shù)有哪些
分享鏈接:http://jinyejixie.com/article30/jjgsso.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁(yè)設(shè)計(jì)公司、網(wǎng)站策劃、建站公司、網(wǎng)站排名、定制網(wǎng)站、網(wǎng)站營(yíng)銷
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)