Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Analysis of heap_insert->XLogInsert function in PostgreSQL

2025-03-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Database >

Share

Shulou(Shulou.com)05/31 Report--

< Insert->

RedoRecPtr); RedoRecPtr = Insert- > RedoRecPtr;} doPageWrites = (Insert- > fullPageWrites | | Insert- > forcePageWrites); if (doPageWrites & & (! prevDoPageWrites | | (fpw_lsn! = InvalidXLogRecPtr & & fpw_lsn info_lck); / * advance global request to include new block (s) * / / advance request to include new block (s) if (XLogCtl- > LogwrtRqst.Write)

< EndPos) XLogCtl->

LogwrtRqst.Write = EndPos; / * update local result copy while I have the chance * / / if you have the opportunity, update the local result copy LogwrtResult = XLogCtl- > LogwrtResult; SpinLockRelease (& XLogCtl- > info_lck);} / * If this was an XLOG_SWITCH record, flush the record and the empty * padding space that fills the rest of the segment, and perform * end-of-segment actions (eg, notifying archiver). * if this is a XLOG_SWITCH record, * refresh the record and fill in the blank space for the rest of the paragraph, * and perform a segment end operation (for example, notify the archiver). * / if (isLogSwitch) {TRACE_POSTGRESQL_WAL_SWITCH (); XLogFlush (EndPos); / * * Even though we reserved the rest of the segment for us, which is * reflected in EndPos, we return a pointer to just the end of the * xlog-switch record. * even if we keep the rest of the segment for ourselves (which is reflected in EndPos), * we only return a pointer to the end of the xlog-switch record. * / if (inserted) {EndPos = StartPos + SizeOfXLogRecord; if (StartPos / XLOG_BLCKSZ! = EndPos / XLOG_BLCKSZ) {uint64 offset = XLogSegmentOffset (EndPos, wal_segment_size); if (offset = = EndPos% XLOG_BLCKSZ) EndPos + = SizeOfXLogLongPHD Else EndPos + = SizeOfXLogShortPHD;}} # ifdef WAL_DEBUG//DEBUG Code if (XLOG_DEBUG) {static XLogReaderState * debug_reader = NULL; StringInfoData buf; StringInfoData recordBuf; char * errormsg = NULL; MemoryContext oldCxt; oldCxt = MemoryContextSwitchTo (walDebugCxt); initStringInfo (& buf) AppendStringInfo (& buf, "INSERT @% X contiguous chunk% X:", (uint32) (EndPos > > 32), (uint32) EndPos); / * We have to piece together the WAL record data from the XLogRecData * entries, so that we can pass it to the rm_desc function as one * contiguous chunk. * / initStringInfo (& recordBuf); for (; rdata! = NULL; rdata = rdata- > next) appendBinaryStringInfo (& recordBuf, rdata- > data, rdata- > len); if (! debug_reader) debug_reader = XLogReaderAllocate (wal_segment_size, NULL, NULL); if (! debug_reader) {appendStringInfoString (& buf, "error decoding record: out of memory") } else if (! DecodeXLogRecord (debug_reader, (XLogRecord *) recordBuf.data, & errormsg)) {appendStringInfo (& buf, "error decoding record:% s", errormsg? Errormsg: "no error message");} else {appendStringInfoString (& buf, "-"); xlog_outdesc (& buf, debug_reader);} elog (LOG, "% s", buf.data); pfree (buf.data); pfree (recordBuf.data); MemoryContextSwitchTo (oldCxt) } # endif / * * Update our global variables * Update global variable * / ProcLastRecPtr = StartPos; XactLastRecEnd = EndPos; return EndPos;} III. Tracking analysis

The test script is as follows

Insert into t_wal_partition (C1, c2, c3) VALUES (0, HASH0, HASH0, HAHS0')

Start gdb, set breakpoints, and enter XLogInsert

(gdb) b XLogInsertBreakpoint 1 at 0x5652d6: file xloginsert.c, line 420. (gdb) cContinuing.Breakpoint 1, XLogInsert (rmid=10'\ n', info=0'\ 000') at xloginsert.c:420420 if (! begininsert_called)

Previously, XLogBeginInsert () must have been called

420 if (! begininsert_called) (gdb) n

The caller must set the rmgrbit: XLR_SPECIAL_REL_UPDATE & XLR_CHECK_CONSISTENCY. The rest is reserved for use here

427 if ((info & ~ (XLR_RMGR_INFO_MASK | (gdb) n432 TRACE_POSTGRESQL_WAL_INSERT (rmid, info))

Enter the cycle

(gdb) n438 if (IsBootstrapProcessingMode () & & rmid! = RM_XLOG_ID) (gdb) 457 GetFullPageWriteInfo (& RedoRecPtr, & doPageWrites)

Gets the value required to determine whether to perform a full-page write

(gdb) p * RedoRecPtr$1 = 1166604425 (gdb) p doPageWrites$2 = false (gdb) n459 rdt = XLogRecordAssemble (rmid, info, RedoRecPtr, doPageWrites, (gdb) p RedoRecPtr$3 = 5411227832 (gdb) p doPageWrites$4 = true

Get rdt

(gdb) n462 EndPos = XLogInsertRecord (rdt, fpw_lsn, curinsert_flags); (gdb) p * rdt$5 = {next = 0x2a911b8, data = 0x2a8f460, len = 51}

XLogInsertRecord- > call XLogInsertRecord to enter the XLogInsertRecord function

Fpw_lsn=0, flags=1'\ 001'

(gdb) stepXLogInsertRecord (rdata=0xf9cc70, fpw_lsn=0, flags=1'\ 001') at xlog.c:970970 XLogCtlInsert * Insert = & XLogCtl- > Insert

XLogInsertRecord- > get insert Manager

(gdb) n973 XLogRecord * rechdr = (XLogRecord *) rdata- > data; (gdb) p * Insert$6 = {insertpos_lck = 0'\ 000mm, CurrBytePos = 5395369608, PrevBytePos = 5395369552, pad ='\ 000mm, RedoRecPtr = 5411227832, forcePageWrites = false, fullPageWrites = true, exclusiveBackupState = EXCLUSIVE_BACKUP_NONE, nonExclusiveBackups = 0, lastBackupStart = 0, WALInsertLocks = 0x7fa2523d4100}

XLogInsertRecord- > variable assignment

(gdb) n974 uint8 info = rechdr- > xl_info & ~ XLR_INFO_MASK; (gdb) 975 bool isLogSwitch = (rechdr- > xl_rmid = = RM_XLOG_ID & & (gdb) 979 bool prevDoPageWrites = doPageWrites; (gdb) 982 Assert (rdata- > len > = SizeOfXLogRecord) (gdb) (gdb) p * rechdr$7 = {xl_tot_len = 210, xl_xid = 1948, xl_prev = 0, xl_info = 0'\ 000mm, xl_rmid = 10'\ 000mm, xl_crc = 3212449170} (gdb) p info$8 = 0'\ 000' (gdb) p isLogSwitch$9 = false (gdb) p prevDoPageWrites$10 = true

XLogInsertRecord- > execute the relevant judgment, open CRIT_SECTION, and obtain the WAL insert lock

(gdb) n985 if (! XLogInsertAllowed ()) (gdb) 1020 START_CRIT_SECTION (); (gdb) 1021 if (isLogSwitch) (gdb) 1024 WALInsertLockAcquire (); (gdb) 1042 if (RedoRecPtr! = Insert- > RedoRecPtr) (gdb)

XLogInsertRecord- > execute relevant judgments and update doPageWrites

(gdb) p RedoRecPtr$11 = 5411227832 (gdb) p Insert- > RedoRecPtr$12 = 5411227832 (gdb) n1047 doPageWrites = (Insert- > fullPageWrites | | Insert- > forcePageWrites); (gdb) 1049 if (doPageWrites & & (gdb) p doPageWrites$13 = true (gdb) n1050 (! prevDoPageWrites | (gdb) 1049 if (doPageWrites & &)

XLogInsertRecord- > Reserve record space in WAL. The xl_prev pointer is also set.

(gdb) 1050 (! prevDoPageWrites | | (gdb) 1066 if (isLogSwitch) (gdb) 1070 ReserveXLogInsertLocation (rechdr- > xl_tot_len, & StartPos, & EndPos, (gdb) 1072 inserted = true; (gdb) p rechdr- > xl_tot_len$14 = 210 (gdb) p StartPos$15 = 5411228000 (gdb) p EndPos$16 = 5411228216 (gdb) p * rechdr- > xl_prevCannot access memory at address 0x14288c928 (gdb) p rechdr- > xl_prev$17 = 5411227944 (gdb)

XLogInsertRecord- > now that the xl_prev pointer is populated, calculate the CRC of the record header

(gdb) n1075 if (inserted) (gdb) 1081 rdata_crc = rechdr- > xl_crc; (gdb) 1082 COMP_CRC32C (rdata_crc, rechdr, offsetof (XLogRecord, xl_crc)); (gdb) 1083 FIN_CRC32C (rdata_crc); (gdb) 1084 rechdr- > xl_crc = rdata_crc (gdb) 1090 CopyXLogRecordToWAL (rechdr- > xl_tot_len, isLogSwitch, rdata, (gdb) p rdata_crc$18 = 2310972234 (gdb) p * rechdr$19 = {xl_tot_len = 210, xl_xid = 1948, xl_prev = 5411227944, xl_info = 0'\ 000mm, xl_rmid = 10'\ n, xl_crc = 2310972234} (gdb)

XLogInsertRecord- > all recorded data, including header data has been OK, ready to insert! Copy the record into the reserved space.

Update the LSN of the last important record in the current slot unless the record is marked as unimportant.

(gdb) n1098 if ((flags & XLOG_MARK_UNIMPORTANT) = = 0) (gdb) 1100 int lockno = holdingAllLocks? 0: MyLockNo; (gdb) (gdb) n1102 WALInsertLockslockno .l.lastImportantAt = StartPos; (gdb) 1117 WALInsertLockRelease ()

XLogInsertRecord- > all done! Let the other inserters know we've done it!

For example, update the shared LogwrtRqst.Write variable across the page boundary

(gdb) 1117 WALInsertLockRelease (); (gdb) n1119 MarkCurrentTransactionIdLoggedIfAny (); (gdb) 1121 END_CRIT_SECTION (); (gdb) 1126 if (StartPos / XLOG_BLCKSZ! = EndPos / XLOG_BLCKSZ) (gdb) 1142 if (isLogSwitch)

XLogInsertRecord- > updates the global variable, the function returns

(gdb) 1220 ProcLastRecPtr = StartPos; (gdb) 1221 XactLastRecEnd = EndPos; (gdb) 1223 return EndPos; (gdb) 1224}

Return XLogInsert, reset insertion, return EndPos, end

(gdb) XLogInsert (rmid=10'\ ntrees, info=0'\ 000') at xloginsert.c:463463} while (EndPos = = InvalidXLogRecPtr); (gdb) n465 XLogResetInsertion (); (gdb) 467 return EndPos; (gdb) 468} (gdb) p EndPos$20 = 5411228216 (gdb) $21 = 5411228216 (gdb) nheap_insert (relation=0x7fa280616228, tup=0x2b15440, cid=0, options=0, bistate=0x0) at heapam.c:25902590 PageSetLSN (page, recptr) (gdb) the content of "heap_insert- > XLogInsert function Analysis in PostgreSQL" ends here. Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Database

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report