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

Interpretation of PostgreSQL Source Code-WAL#7 (Insert&WAL-XLogRe...)

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Database >

Share

Shulou(Shulou.com)06/01 Report--

This section focuses on tracking and analyzing the processing of FPW (full-page-write) in the XLogRecordAssemble function.

I. data structure

Global static variable

Global variables used by XLogRecordAssemble include hdr_rdt/hdr_scratch/rdatas and so on.

/ * flags for the in-progress insertion * / / the tag information used in the insertion process static uint8 curinsert_flags = 0 These are used to hold the record header while constructing a record * *. * 'hdr_scratch' is not a plain variable, but is palloc'd at initialization, * because we want it to be MAXALIGNed and padding bytes zeroed. * the header information of the record is usually stored when building a XLOG Record. * 'hdr_scratch' is not a plain variable, but is initialized with palloc during initialization, * because we want the variable to be MAXALIGNed and populated by 0x00. * For simplicity, it's allocated large enough to hold the headers for any * WAL record. * for simplicity, this variable allocates enough space in advance to store all WAL Record header information. * / static XLogRecData hdr_rdt;static char * hdr_scratch = NULL;#define SizeOfXlogOrigin (sizeof (RepOriginId) + sizeof (char)) # define HEADER_SCRATCH_SIZE\ (SizeOfXLogRecord +\ MaxSizeOfXLogRecordBlockHeader * (XLR_MAX_BLOCK_ID + 1) +\ SizeOfXLogRecordDataHeaderLong + SizeOfXlogOrigin) / * * An array of XLogRecData structs, to hold registered data. * XLogRecData structure array to store registered data. * / static XLogRecData * rdatas;static int num_rdatas; / * entries currently used * / / the allocated space static int max_rdatas; / * allocated size * / / whether to call the XLogBeginInsert function static bool begininsert_called = false;static XLogCtlData * XLogCtl = NULL;/* flags for the in-progress insertion * / static uint8 curinsert_flags = 0 * A chain of XLogRecDatas to hold the "main data" of a WAL record, registered * with XLogRegisterData (...). * store the XLogRecDatas data link of WAL Record "main data" * / static XLogRecData * mainrdata_head;static XLogRecData * mainrdata_last = (XLogRecData *) & the mainrdata size of a location in the mainrdata_head;// chain static uint32 mainrdata_len; / * total # of bytes in chain * / / * ProcLastRecPtr points to the start of the last XLOG record inserted by the * current backend. It is updated for all inserts. XactLastRecEnd points to * end+1 of the last record, and is reset when we end a top-level transaction, * or start a new one; so it can be used to tell if the current transaction has * created any XLOG records. * ProcLastRecPtr points to the beginning of the last XLOG record inserted by the current backend. * it updates for all inserts. * XactLastRecEnd points to + 1 at the end of the last record, * and resets when ending a top-level transaction or starting a new transaction; * therefore, it can be used to determine whether any XLOG records have been created by the current transaction. * While in parallel mode, this may not be fully up to date. When committing, * a transaction can assume this covers all xlog records written either by the * user backend or by any parallel worker which was present at any point during * the transaction. But when aborting, or when still in parallel mode, other * parallel backends may have written WAL records at later LSNs than the value * stored here. The parallel leader advances its own copy, when necessary, * in WaitForParallelWorkersToFinish. * in parallel mode, this may not be entirely up to date. * at the time of commit, the transaction can be assumed to overwrite all xlog records of the user background process or parallel worker processes that occur during the transaction. * however, when aborted, or when still in parallel mode, other parallel background processes may have written WAL records in a later LSNs, * instead of the values stored here. * the leader of the parallel processing process pushes its own copy in WaitForParallelWorkersToFinish when needed. * / XLogRecPtr ProcLastRecPtr = InvalidXLogRecPtr;XLogRecPtr XactLastRecEnd = InvalidXLogRecPtr;XLogRecPtr XactLastCommitEnd = InvalidXLogRecPtr;/* For WALInsertLockAcquire/Release functions * / for the WALInsertLockAcquire/Release function static int MyLockNo = 0 position static bool holdingAllLocks = false

Macro definition

The flags used by the XLogRegisterBuffer function

/ * flags for XLogRegisterBuffer * / the flags#define REGBUF_FORCE_IMAGE 0x01 / * used by the XLogRegisterBuffer function to enforce full-page-write;force a full-page image * / # define REGBUF_NO_IMAGE 0x02 / * does not require FPI;don't take a full-page image * / # define REGBUF_WILL_INIT (0x04 | 0x02) / * reinitialize page on playback (indicates NO_IMAGE) * page will be re-initialized at * replay (implies NO_IMAGE) * / # define REGBUF_STANDARD 0x08 / * Standard page layout (data between pd_lower and pd_upper will be skipped) * page follows "standard" page layout * (data between pd_lower and pd_upper * will be skipped) * / # define REGBUF_KEEP_DATA 0x10 / * include data even if a full-page image * is taken * / / * * Flag bits for the record being inserted, set using XLogSetRecordFlags (). * / # define XLOG_INCLUDE_ORIGIN 0x01 / * include the replication origin * / # define XLOG_MARK_UNIMPORTANT 0x02 / * record not important for durability * /

XLogRecData

The functions in xloginsert.c construct a chain of XLogRecData structures to identify the last WAL record

/ * * The functions in xloginsert.c construct a chain of XLogRecData structs * to represent the final WAL record. * the function in xloginsert.c constructs a XLogRecData structure chain to identify the next structure in the last WAL record * / typedef struct XLogRecData {/ / chain. If none, it is the starting address of NULL struct XLogRecData * next; / * next struct in chain, or NULL * / rmgr data starting address char * data; / * start of rmgr data to include * / / rmgr data size uint32 len / * length of rmgr data to include * /} XLogRecData

Registered_buffer

For each data block registered with XLogRegisterBuffer, populate it into the registered_buffer structure

/ * * For each block reference registered with XLogRegisterBuffer, we fill in * a registered_buffer struct. * for every data block registered with XLogRegisterBuffer, * populated into the registered_buffer structure * / typedef struct {/ / slot is in use? Bool in_use; / * is this slot in use? * / / REGBUF_* related tags uint8 flags; / * REGBUF_* flags * / / define identifiers for relationships and databases RelFileNode rnode; / * identifies the relation and block * / fork process number ForkNumber forkno; / / block number BlockNumber block / / Page content Page page; / * page content * / / Total data size in the rdata chain uint32 rdata_len; / * total length of data in rdata chain * / data link header XLogRecData * rdata_head registered with this data block / * head of the chain of data registered with * this block * / / XLogRecData * rdata_tail; / * last entry in the chain, or & rdata_head if * empty * / / temporary rdatas data reference registered with this data block, used to store backup block data XLogRecData bkp_rdatas used in XLogRecordAssemble () [2] / * temporary rdatas used to hold references to * backup block data in XLogRecordAssemble () * / / * buffer to store a compressed version of backup block image * / / the cache char compressed_ page used to store the compressed version of the backup block image [PGLZ _ MAX_BLCKSZ];} registered_buffer;//registered_buffer pointer (global variable) static registered_buffer * registered_buffers / / assigned size static int max_registered_buffers; / * allocated size * / / maximum block number + 1 (currently registered block) static int max_registered_block_id = 0; / * highest block_id + 1 currently * registered * /

Definition of rmid (Resource Manager ID)

0 XLOG

1 Transaction

2 Storage

3 CLOG

4 Database

5 Tablespace

6 MultiXact

7 RelMap

8 Standby

9 Heap2

10 Heap

11 Btree

12 Hash

13 Gin

14 Gist

15 Sequence

16 SPGist

Second, source code interpretation

The XLogRecordAssemble function assembles the XLOG record from the registered data and buffer into the XLogRecData chain, and after assembly, it can be inserted into the WAL buffer using the XLogInsertRecord () function.

See the previous section for details

Third, follow-up analysis

Scenario 2: insert the nth record in the data table

The test script is as follows:

Testdb=# drop table tactile walkers: drop TABLEtestdb=# create table t_wal_normal (C1 int not null,c2 varchar (40), c3 varchar (40)); CREATE TABLEtestdb=# insert into t_wal_normal (C1 int not null,c2 varchar (40), c2 varchar (40)) select iFinder C2lily'| | I from generate_series (1meme 8191) as itincence insert 0 8191testdb=# select pg_size_pretty (pg_relation_size ('tactile walkers')) Pg_size_pretty-424 kB (1 row) testdb=# checkpoint;CHECKPOINTtestdb=# insert into t_wal_normal (C1 to c2 and c3) VALUES (8192 to C2-8192)

Set breakpoint and enter XLogRecordAssemble

(gdb) b XLogRecordAssembleBreakpoint 1 at 0x565411: file xloginsert.c, line 488. (gdb) cContinuing.Breakpoint 1, XLogRecordAssemble (rmid=10'\ nfolk, info=0'\ 000mm, RedoRecPtr=5509173376, doPageWrites=true, fpw_lsn=0x7ffd7eb51408) at xloginsert.c:488488 uint32 total_len = 0

Enter parameters:

Rmid=10 is 0x0A-- > Heap

Info=0'\ 000'

RedoRecPtr=5509173376, the hexadecimal value is 0x00000001485F5080

DoPageWrites=true, need full-page-write

Fpw_lsn=0x7ffd7eb51408 (fpw is short for full-page-write, note that this variable is not yet assigned)

Then there is variable assignment.

Hdr_scratch is defined as: static char * hdr_scratch = NULL

Hdr_rdt is defined as: static XLogRecData hdr_rdt

(gdb) n491 registered_buffer * prev_regbuf = NULL; (gdb) 494 char * scratch = hdr_scratch; (gdb) 502 rechdr = (XLogRecord *) scratch; (gdb) 503 scratch + = SizeOfXLogRecord; (gdb) p * (XLogRecord *) rechdr$1 = {xl_tot_len = 0, xl_xid = 0, xl_prev = 0, xl_info = 0'\ 000, xl_rmid = 0'\ 000, xl_crc = 0} (gdb) p hdr_scratch$2 = 0x1f6a4c0 "(gdb)

Configure hdr_rdt (for storing header information)

(gdb) n505 hdr_rdt.next = NULL; (gdb) 506 rdt_datas_last = & hdr_rdt; (gdb) n507 hdr_rdt.data = hdr_scratch; (gdb) 515 if (wal_consistency_ checking [rmid])

Full-page-write's LSN initialization

(gdb) n523 * fpw_lsn = InvalidXLogRecPtr; (gdb) 524 for (block_id = 0; block_id)

< max_registered_block_id; block_id++)(gdb) p max_registered_block_id$7 = 1 开始循环,获取regbuf. regbuf是使用 (gdb) n526 registered_buffer *regbuf = ®istered_buffers[block_id];(gdb) 531 XLogRecordBlockCompressHeader cbimg = {0};(gdb) 533 bool is_compressed = false;(gdb) p *regbuf$3 = {in_use = true, flags = 8 '\b', rnode = {spcNode = 1663, dbNode = 16402, relNode = 25271}, forkno = MAIN_FORKNUM, block = 52, page = 0x7f391f91b380 "\001", rdata_len = 26, rdata_head = 0x1f6a2c0, rdata_tail = 0x1f6a2d8, bkp_rdatas = {{ next = 0x0, data = 0x0, len = 0}, {next = 0x0, data = 0x0, len = 0}}, compressed_page = '\000' }(gdb)################testdb=# select oid,relname,reltablespace from pg_class where relfilenode = 25271; oid | relname | reltablespace -------+--------------+--------------- 25271 | t_wal_normal | 0(1 row)############## 注意: 在内存中,main data已由函数XLogRegisterData注册,由mainrdata_head和mainrdata_last指针维护,本例中,填充了xl_heap_insert结构体. block data由XLogRegisterBuffer初始化,通过XLogRegisterBufData注册(填充)数据,分别是xl_heap_header结构体和实际数据(实质上是char *指针,最终填充的数据,由组装器确定). 1.main data (gdb) p *mainrdata_head$4 = {next = 0x0, data = 0x7ffd7eb51480 "\r", len = 3}(gdb) p *(xl_heap_insert *)regbuf->

Rdata_head- > data$8 = {offnum = 3, flags = 2'\ 002'} (gdb)

2.block data-> xl_heap_header

(gdb) p * regbuf- > rdata_head$6 = {next = 0x1f6a2d8, data = 0x7ffd7eb51470 "\ 003", len = 5} (gdb) p * (xl_heap_header *) regbuf- > rdata_head- > data$7 = {t_infomask2 = 3, t_infomask = 2050, t_hoff = 24'\ 030'} (gdb)

3.block data-> tuple data

(gdb) p * regbuf- > rdata_head- > next$9 = {next = 0x0, data = 0x1feb07f "", len = 21}

Look at the 21 bytes of data at the beginning of the address 0x1feb07f and point to the actual data.

The first field: the first byte 0'\ 000' is the type identifier (INT), and the next four bytes are 32bit integer 0x00002000, that is, the integer 8192.

The second field: the first byte 17'\ 021' is the type identifier (VARCHAR), followed by the actual data, that is, C2-8192

Third field: similar to the second field (C3-8192)

(gdb) x/21bc 0x1feb07f0x1feb07f: 0'\ 000' 0'\ 00032'0'\ 000' 0' 17'\ 021' 67'C' 50 '2'0x1feb087: 45' -'56'8' 49'1' 57'9' 50'2' 17'\ 021' 67'C' 51 '3'0x1feb08f: 45' -'56'8' 49'1' 57'9' 50'2'(gdb)

4.block data-> backup block image

This section is populated by the XLogRecordAssemble () function.

Continue to execute the subsequent logic, regbuf- > flags=0x08 represents REGBUF_STANDARD (standard page layout)

(gdb) n536 if (! regbuf- > in_use) (gdb) 540 if (regbuf- > flags & REGBUF_FORCE_IMAGE) (gdb) p regbuf- > flags$10 = 8'\ b'

DoPageWrites = T, need to execute full-page-write.

Page_lsn = 5509173336, the hexadecimal value is 0x00000001485F5058, the logical ID is 0x00000001, the physical ID is 0x00000048, and the physical ID is 0x00000048. The text file name is 00000001 000001 000048 (timeline is 0x00000001), and the intra-file offset is 0x5F5058.

(gdb) n542 else if (regbuf- > flags & REGBUF_NO_IMAGE) (gdb) 544 else if (! doPageWrites) (gdb) 553 XLogRecPtr page_lsn = PageGetLSN (regbuf- > page); (gdb) 555 needs_backup = (page_lsn rdata_len = = 0) (gdb) n566 else if ((regbuf- > flags & REGBUF_KEEP_DATA)! = 0) (gdb) 569 needs_data =! needs_backup; (gdb) 571 bkpb.id = block_id (gdb) p needs_data$14 = false (gdb)

Configure BlockHeader

(gdb) n572 bkpb.fork_flags = regbuf- > forkno; (gdb) 573 bkpb.data_length = 0; (gdb) 575 if ((regbuf- > flags & REGBUF_WILL_INIT) = = REGBUF_WILL_INIT) (gdb) 582 include_image = needs_backup | | (info & XLR_CHECK_CONSISTENCY)! = 0 (gdb) 584 if (include_image) (gdb) p bkpb$15 = {id = 0'\ 000mm, fork_flags = 0'\ 000mm, data_length = 0} (gdb) p include_image$16 = true (gdb)

It is required to include a block image (FPI), and get the corresponding page (pointer to 64bit)

(gdb) n586 Page page = regbuf- > page; (gdb) 587 uint16 compressed_len = 0; (gdb) 593 if (regbuf- > flags & REGBUF_STANDARD) (gdb) p page$17 = (Page) 0x7f391f91b380 "\ 001"

View page content

(gdb) x/8192bx 0x7f391f91b3800x7f391f91b380: 0x01 0x00 0x00 0x00 0x40 0x6b 0x76 0x480x7f391f91b388: 0x00 0x00 0x00 0x00 0x4c 0x00 0x90 0x1d0x7f391f91b390: 0x00 0x20 0x04 0x20 0x000 X00 0x00 0x000x7f391f91b398: 0xd0 0x9f 0x58 0x00 0xa0 0x9f 0x58 0x000x7f391f91b3a0: 0x70 0x9f 0x58 0x00 0x40 0x9f 0x58 0x000x7f391f91b3a8: 0x10 0x9f 0x58 0x00 0xe0 0x9e 0x58 0x000x7f391f91b3b0: 0xb0 0x9e 0x58 0x00 0x80 0x9e 0x58 0x000x7f391f91b3b8: 0x50 0x9e 0x58 0x00 0x20 0x9e 0x58 0x000x7f391f91b3c0: 0xf0 0x9d 0x58 0x00 0xc0 0x9d 0x58 0x000x7f391f91b3c8: 0x90 0x9d 0x58 0x00 0x00 0x00 0x00 0x000x7f391f91b3d0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x000x7f391f91b3d8: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x000x7f391f91b3e0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00-- > header data... 0x7f391f91d330: 0x02 0x00 0x03 0x00 0x02 0x09 0x18 0x000x7f391f91d338: 0xf5 0x1f 0x00 0x00 0x11 0x43 0x32 0x2d0x7f391f91d340: 0x38 0x31 0x38 0x31 0x11 0x43 0x33 0x2d0x7f391f91d348: 0x38 0x31 0x38 0x31 0x00 0x00 0x00 0x000x7f391f91d350: 0xe7 0x07 0x00 0x00 0x00 0x00 0x00 0x000x7f391f91d358: 0x00 0x00 0x00 0x00 0x00 0x000x 34 0x000x7f391f91d360: 0x01 0x00 0x03 0x00 0x02 0x09 0x18 0x000x7f391f91d368: 0xf4 0x1f 0x00 0x00 0x11 0x43 0x32 0x2d0x7f391f91d370: 0x38 0x31 0x38 0x30 0x11 0x43 0x33 0x2d0x7f391f91d378: 0x38 0x31 0x38 0x30 0x00 0x00 0x00 0x00-- > partial tail data

Switch to character format to view the data started by 0x7f391f91d330

(gdb) x/80bc 0x7f391f91d3300x7f391f91d330: 2'\ 0020'\ 0003'\ 0030'\ 0002'\ 0029'\ t24'\ 0300'\ 000'0x7f391f91d338:-11'\ 36531'\ 0370'\ 00000017'\ 021' 67'C' 50 '245'-'0x7f391f91d340: 56' 8' 49'1' 56 '849' 1 '17'\ 021' 67'C' 51'3' 45'- '0x7f391f91d348: 56' 8' 49'1' 56 '849' 1' 0'\ 00000'\ 0000000'\ 0000000'\ 000'0x7f391f91d350:-25'\ 3477'\ a' 0'\ 000room0'\ 000room0'\ 0000000'\ 0000000'\ 0000000'\ 000room0'\ 000'0x7f391f91d358: '000' 0'\ 000'0'\ 000'0'\ 000'0' 52'4' 0'\ 000'0x7f391f91d360: 1'\ 001' 0'\ 0003'\ 0030'\ 0002'\ 0029'\ t'24'\ 0300'\ 000'0x7f391f91d368:-12'\ 364' 31'\ 037' 0'\ 000'0' 17 '021' 67' C'50'2' 45'- '0x7f391f91d370: 56' 8' 49'1' 56'8' 48'0' 17'\ 021' 67'C' 51'3' 45'- '0x7f391f91d378: 56' 8' 49'1' 56 '848' 0' 56 '848' 0'\ 0000'\ 0000'\ 0000' (gdb)

Standard block (REGBUF_STANDARD), get lower&upper, and set hole information

(gdb) n596 uint16 lower = ((PageHeader) page)-> pd_lower; (gdb) 597 uint16 upper = ((PageHeader) page)-> pd_upper; (gdb) 599 if (lower > = SizeOfPageHeaderData & & (gdb) p lower$18 = 76 (gdb) p upper$19 = 7568 (gdb) n600 upper > lower & & (gdb) 603 bimg.hole_offset = lower; (gdb) 604 cbimg.hole_length = upper-lower (gdb) n623 if (wal_compression) (gdb) p bimg$22 = {length = 49648, hole_offset = 76, bimg_info = 0'\ 000'} (gdb) p cbimg$23 = {hole_length = 7492} (gdb)

If compression is not enabled, do not attempt to compress block

(gdb) p wal_compression$24 = false (gdb)

Set the tag BKPBLOCK_HAS_IMAGE

(gdb) n636 bkpb.fork_flags | = BKPBLOCK_HAS_IMAGE; (gdb) 641 rdt_datas_last- > next = & regbuf- > bkp_rdatas [0]; (gdb)

Set up relevant information

(gdb) 641 rdt_datas_last- > next = & regbuf- > bkp_rdatas [0]; (gdb) n642 rdt_datas_last = rdt_datas_last- > next; (gdb) 644 bimg.bimg_info = (cbimg.hole_length = = 0)? 0: BKPIMAGE_HAS_HOLE; (gdb) 652 if (needs_backup)

Set the tag BKPIMAGE_APPLY

(gdb) n653 bimg.bimg_info | = BKPIMAGE_APPLY; (gdb) 655 if (is_compressed) (gdb) p bimg$26 = {length = 49648, hole_offset = 76, bimg_info = 5'\ 005'}

No compressed storage, set related information

(gdb) p is_compressed$27 = false (gdb) n665 bimg.length = BLCKSZ-cbimg.hole_length; (gdb) 667 if (cbimg.hole_length = = 0) (gdb) (gdb) p bimg$28 = {length = 700, hole_offset = 76, bimg_info = 5'\ 005'}

Set the rdt_datas_last variable, build the hdr_rdt linked list, and point to the front part of the hole and the back part of the hole.

675 rdt_datas_last- > data = page; (gdb) 676 rdt_datas_last- > len = bimg.hole_offset; (gdb) 678 rdt_datas_last- > next = & regbuf- > bkp_rdatas [1]; (gdb) 679 rdt_datas_last = rdt_datas_last- > next; (gdb) 682 page + (bimg.hole_offset + cbimg.hole_length) (gdb) 681rdt_datas_last- > data = (gdb) 684BLCKSZ-(bimg.hole_offset + cbimg.hole_length); (gdb) 683rdt_datas_last- > len = (gdb) 688 total_len + = bimg.length

View hdr_rdt related information

(gdb) p hdr_rdt$31 = {next = 0x1f6c218, data = 0x1f6a4c0 "", len = 0} (gdb) p * hdr_rdt- > next$34 = {next = 0x1f6c230, data = 0x7f391f91b380 "\ 001", len = 76} (gdb) p * hdr_rdt- > next- > next$35 = {next = 0x0, data = 0x7f391f91d110 "\ 351a", len = 624} (gdb)

Set Siz

(gdb) n691 if (needs_data) (gdb) p total_len$36 = 700 (gdb)

There is no need to deal with tuple data, not the same REL

(gdb) p needs_data$37 = false (gdb) (gdb) n705 if (prev_regbuf & & RelFileNodeEquals (regbuf- > rnode, prev_regbuf- > rnode)) (gdb) p prev_regbuf$38 = (registered_buffer *) 0x0 (gdb) n711 samerel = false; (gdb) 712 prev_regbuf = regbuf; (gdb)

Copy the header information into the scratch buffer

(gdb) 715 memcpy (scratch, & bkpb, SizeOfXLogRecordBlockHeader); (gdb) 716 scratch + = SizeOfXLogRecordBlockHeader; (gdb)

Include FPI, append SizeOfXLogRecordBlockImageHeader

(gdb) n717 if (include_image) (gdb) 719 memcpy (scratch, & bimg, SizeOfXLogRecordBlockImageHeader); (gdb) 720 scratch + = SizeOfXLogRecordBlockImageHeader; (gdb) 721 if (cbimg.hole_length! = 0 & & is_compressed) (gdb) 728 if (! samerel) (gdb)

Not the same REL, append RelFileNode

728 if! samerel) (gdb) 730 memcpy (scratch, & regbuf- > rnode, sizeof (RelFileNode)); (gdb) 731 scratch + = sizeof (RelFileNode); (gdb)

Followed by blocknumber

733 memcpy (scratch, & regbuf- > block, sizeof (BlockNumber)); (gdb) 734 scratch + = sizeof (BlockNumber)

Move on to the next block

(gdb) 524 for (block_id = 0; block_id)

< max_registered_block_id; block_id++)(gdb) 已处理完毕,接下来,是XLOG Record origin(不需要) (gdb) n738 if ((curinsert_flags & XLOG_INCLUDE_ORIGIN) &&(gdb) 739 replorigin_session_origin != InvalidRepOriginId)(gdb) 738 if ((curinsert_flags & XLOG_INCLUDE_ORIGIN) &&(gdb) 747 if (mainrdata_len >

0) (gdb)

Next is main data, using the XLR_BLOCK_ID_DATA_SHORT format

(gdb) n749 if (mainrdata_len > 255) (gdb) 757 * (scratch++) = (char) XLR_BLOCK_ID_DATA_SHORT; (gdb) p mainrdata_len$39 = 3 (gdb)

Adjust rdt_datas_last variable information, adjust the total size

(gdb) n758 * (scratch++) = (uint8) mainrdata_len; (gdb) 760 rdt_datas_last- > next = mainrdata_head; (gdb) 761 rdt_datas_last = mainrdata_last; (gdb) 762 total_len + = mainrdata_len; (gdb) 764 rdt_datas_last- > next = NULL; (gdb) p total_len$40 = 703 (gdb)

Adjust hdr_rdt information

(gdb) n766 hdr_rdt.len = (scratch-hdr_scratch); (gdb) 767 total_len + = hdr_rdt.len; (gdb) 777 INIT_CRC32C (rdata_crc); (gdb) p hdr_rdt$41 = {next = 0x1f6c218, data = 0x1f6a4c0 "", len = 51} (gdb) p total_len$42 = 754 (gdb)

Calculate CRC

(gdb) 779 for (rdt = hdr_rdt.next; rdt! = NULL; rdt = rdt- > next) (gdb) 780 COMP_CRC32C (rdata_crc, rdt- > data, rdt- > len); (gdb) 779 for (rdt = hdr_rdt.next; rdt! = NULL; rdt = rdt- > next) (gdb) 780 COMP_CRC32C (rdata_crc, rdt- > data, rdt- > len); (gdb) 779 for (rdt = hdr_rdt.next; rdt! = NULL) Rdt = rdt- > next) (gdb) 780 COMP_CRC32C (rdata_crc, rdt- > data, rdt- > len); (gdb) 779 for (rdt = hdr_rdt.next; rdt! = NULL; rdt = rdt- > next) (gdb) 787 rechdr- > xl_xid = GetCurrentTransactionIdIfAny (); (gdb)

Fill in other fields of record header information.

(gdb) n788 rechdr- > xl_tot_len = total_len; (gdb) 789 rechdr- > xl_info = info; (gdb) 790 rechdr- > xl_rmid = rmid; (gdb) 791rechdr- > xl_prev = InvalidXLogRecPtr; (gdb) 792rechdr- > xl_crc = rdata_crc; (gdb) 794return & hdr_rdt (gdb) p * (XLogRecord *) rechdr$43 = {xl_tot_len = 754, xl_xid = 2025, xl_prev = 0, xl_info = 0'\ 000mm, xl_rmid = 10'\ n, xl_crc = 1615792998} (gdb)

Return to hdr_rdt

(gdb) n795} (gdb) XLogInsert (rmid=10'\ n, info=0'\ 000') at xloginsert.c:462462 EndPos = XLogInsertRecord (rdt, fpw_lsn, curinsert_flags); (gdb) (gdb) p * rdt$44 = {next = 0x1f6c218, data = 0x1f6a4c0 "\ 362002", len = 51} (gdb) p fpw_lsn$45 = 0 (gdb) p curinsert_flags$46 = 1'\ 001' (gdb)

DONE!

IV. Reference materials

Write Ahead Logging-WAL

PostgreSQL Source Code interpretation (4)-insert data # 3 (heap_insert)

Analysis of WAL structure of PostgreSQL transaction Log

PostgreSQL Source Code interpretation-WAL#6 (Insert&WAL-XLogRecordAssemble record assembly function)

PG Source Code

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