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

PostgreSQL Source Code interpretation (2)-insert data # 2 (RelationPutHeapTuple)

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

Share

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

< 0) typedef void *Block;//指向任意类型的指针 Block *LocalBufferBlockPointers = NULL;//指针的指针8、BufferGetBlockNumber /* * BufferGetBlockNumber * Returns the block number associated with a buffer. * * Note: * Assumes that the buffer is valid and pinned, else the * value may be obsolete immediately... */ BlockNumber BufferGetBlockNumber(Buffer buffer) { BufferDesc *bufHdr; Assert(BufferIsPinned(buffer)); if (BufferIsLocal(buffer)) bufHdr = GetLocalBufferDescriptor(-buffer - 1); else bufHdr = GetBufferDescriptor(buffer - 1); /* pinned, so OK to read tag without spinlock */ return bufHdr->

Tag.blockNum;} 9, BlockIdSet / * * BlockIdSet * Sets a block identifier to the specified value. * / # define BlockIdSet (blockId, blockNumber)\ (\ AssertMacro (PointerIsValid (blockId)),\ (blockId)-> bi_hi = (blockNumber) > > 16,\ / / move 16 bits to the right to get the high bit (blockId)-> bi_lo = (blockNumber) & 0xffff\ / / the high 16 bits are all set to 0, get the low bit) 10, ItemPointerSet / * * ItemPointerSet * Sets a disk item pointer to the specified block and offset. * / # define ItemPointerSet (pointer, blockNumber, offNum)\ (\ AssertMacro (PointerIsValid (pointer)),\ BlockIdSet (& ((pointer)-> ip_blkid), blockNumber),\ (pointer)-> ip_posid = offNum\) 11, PageGetItemId get row pointer (ItemIdData pointer) / * * PageGetItemId * Returns an item identifier of a page. * / # define PageGetItemId (page, offsetNumber)\ ((ItemId) (& (PageHeader) (page))-> pd_linp [(offsetNumber)-1]) 12. PageGetItem obtains the corresponding Item (Tuple) / * * PageGetItem * Retrieves an item on the given page according to ItemId. * * Note: * This does not change the status of any of the resources passed. * The semantics may change in the future. * / # define PageGetItem (page, itemId)\ (\ AssertMacro (PageIsValid (page)),\ AssertMacro (ItemIdHasStorage (itemId)),\ (Item) (char *) (page)) + ItemIdGetOffset (itemId))\) # define ItemIdGetOffset (itemId)\ ((itemId)-> lp_off) II. Source code interpretation / * * RelationPutHeapTuple-place tuple at specified page * *! EREPORT (ERROR) IS DISALLOWED HERE! Must PANIC on failure diagnosis! * * Note-caller must hold BUFFER_LOCK_EXCLUSIVE on the buffer. * / voidRelationPutHeapTuple (Relation relation, Buffer buffer, HeapTuple tuple, bool token) {Page pageHeader;// header OffsetNumber offnum;// line offset / * * A tuple that's being inserted speculatively should already have its * token set. * / / TODO token & speculatively to be studied Assert (! token | | HeapTupleHeaderIsSpeculative (tuple- > t_data)); / * Add the tuple to the page * / / get the corresponding page (header) pageHeader = BufferGetPage (buffer) according to buffer / / insert data. As described in the previous section of the PageAddItem function, the function successfully returned row offset / * input: page- pointer to Page item- to data pointer size- data size offsetNumber- data store offset InvalidOffsetNumber means do not specify flags- not to "overwrite" the original is_heap-Heap data output: OffsetNumber- data store actual offset * / offnum = PageAddItem (pageHeader, (Item) tuple- > t_data, tuple- > t_len, InvalidOffsetNumber, false, true) / / if it is not successful, log if (offnum = = InvalidOffsetNumber) elog (PANIC, "failed to add tuple to page") / * Update tuple- > t_self to the actual position where it was stored * / / & (tuple- > t_self) type is ItemPointer, that is, the row pointer (ItemPointerData structure pointer) / / gets the block number according to buffer, and writes the block number and row offset to the row pointer ItemPointerSet (& (tuple- > t_self), BufferGetBlockNumber (buffer), offnum) / * * Insert the correct position into CTID of the stored tuple, too (unless * this is a speculative insertion, in which case the token is held in * CTID field instead) * / if (! token) {/ / get row pointer, ItemId is ItemIdData pointer ItemId itemId = PageGetItemId (pageHeader, offnum); / / get TupleHeader HeapTupleHeader item = (HeapTupleHeader) PageGetItem (pageHeader, itemId) / / Update the row pointer item- > t_ctid = tuple- > tweeself;}} in TupleHeader.

Using the data table in the previous section, after garbage collection, insert a record.

Testdb=# vacuum tweak insert: VACUMtestDB # testdb=# checkpoint;CHECKPOINTtestdb=# select pg_backend_pid (); pg_backend_pid-1582 (1 row)

Use gdb for tracking analysis:

[root@localhost] # gdb-p 1582GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-100.el7... (gdb)

Insert a record:

Testdb=#-insert 1 line of testdb=# insert into t_insert values (10 minutes 10 minutes); (hangs)

Go back to gdb:

(gdb) b RelationPutHeapTupleBreakpoint 1 at 0x4cf492: file hio.c, line 51.# View the input parameters (gdb) p * relation$5 = {rd_node = {spcNode = 1663, dbNode = 16477, relNode = 26731}, rd_smgr = 0x259db68, rd_refcnt = 1, rd_backend =-1, rd_islocaltemp = false, rd_isnailed = false, rd_isvalid = true, rd_indexvalid = 0000, rd_statvalid = false, rd_createSubid = 0, rd_newRelfilenodeSubid = 0, rd_rel = 0x7fa9814589e8, rd_att = 0x7fa981458af8 Rd_id = 26731, rd_lockInfo = {relId = 26731, dbId = 16477}}, rd_rules = 0x0, rd_rulescxt = 0x0, trigdesc = 0x0, rd_rsdesc = 0x0, rd_fkeylist = 0x0, rd_fkeyvalid = false, rd_partkeycxt = 0x0, rd_partkey = 0x0, rd_pdcxt = 0x0, rd_partdesc = 0x0, rd_partcheck = 0x0, rd_indexlist = 0x0, rd_oidindex = 0, rd_pkindex = 0, rd_replidindex = 0, rd_statlist = 0x0, rd_indexattr = 0x0 Rd_projindexattr = 0x0, rd_keyattr = 0x0, rd_pkattr = 0x0, rd_idattr = 0x0, rd_projidx = 0x0, rd_pubactions = 0x0, rd_options = 0x0, rd_index = 0x0, rd_indextuple = 0x0, rd_amhandler = 0, rd_indexcxt = 0x0, rd_amroutine = 0x0, rd_opfamily = 0x0, rd_opcintype = 0x0, rd_support = 0x0, rd_supportinfo = 0x0, rd_indoption = 0x0, rd_indexprs = 0x0, rd_indpred = rd_indpred, 0x0 = 0x0, 0x0 = rd_exclops Rd_exclstrats = 0x0, rd_amcache = 0x0, rd_indcollation = 0x0, rd_fdwroutine = 0x0, rd_toastoid = 0, pgstat_info = 0x2591850} (gdb) p buffer$6 = 95 (gdb) p tuple$7 = (HeapTuple) 0x2539a20 (gdb) p * tuple # Note: HeapTuple$8 = {t_len = 61, t_self = {ip_blkid = {bi_hi = 65535, bi_lo = 65535}, ip_posid = 0}, t_tableOid = 26731 T_data = 0x2539a38} (gdb) p * tuple- > t_data # Note: HeapTupleHeader$9 = {t_choice = {t_heap = {t_xmin = 1612851, t_xmax = 0, t_field3 = {t_cid = 0, t_xvac = 0}}, t_datum = {datum_len_ = 1612851, datum_typmod = 0, datum_typeid = 0}}, t_ctid = {ip_blkid = {bi_hi = 65535, bi_lo = 65535}, ip_posid = 0}, t_infomask2 = 4 T_infomask = 2050, t_hoff = 24'\ 030, t_bits = 0x2539a4f ""} (gdb) p token$10 = false# View PageHeader information (gdb) p * (PageHeader) pageHeader$11 = {pd_lsn = {xlogid = 1, xrecoff = 3677464616}, pd_checksum = 0, pd_flags = 5, pd_lower = 60, pd_upper = 7680, pd_special = 8192, pd_pagesize_version = 8196, pd_prune_xid = 0 Pd_linp = 0x7fa96957d318} # after calling the PageAddItem function (gdb) next56 if (offnum = = InvalidOffsetNumber) (gdb) p offnum # 2 Item is deleted After performing vacuum recycling $12 = 2 (gdb) p * itemId$13 = {lp_off = 7616, lp_flags = 1, lp_len = 61} (gdb) p * item$14 = {t_choice = {t_heap = {t_xmin = 1612851, t_xmax = 0, t_field3 = {t_cid = 0, t_xvac = 0}}, t_datum = {datum_len_ = 1612851, datum_typmod = 0, datum_typeid = 0}}, t_ctid = {ip_blkid = {bi_hi = 65535} Bi_lo = 65535}, ip_posid = 0}, t_infomask2 = 4, t_infomask = 2050, t_hoff = 24'\ 030mm, t_bits = 0x7fa96957f0d7 ""} (gdb) next74} (gdb) p * itemNo symbol "item" in current context. (gdb) p tuple- > t_self$15 = {ip_blkid = {bi_hi = 0, bi_lo = 0}, ip_posid = 2} # 0 Block Offset 2 (gdb) cContinuing.

As you can see, this row of data is "correctly" inserted at the offset of Block,2 0.

IV. Summary

1. Basically understand the implementation logic of RelationPutHeapTuple function and related data structures.

2. On the basis of being familiar with data structures (including macro definitions & general functions), reading the source code and debugging with gdb can deeply grasp the logic behind PG's processing of data.

The next section will talk about the heap_insert function in the call stack.

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