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

What is the function of RelationGetBufferForTuple function in PostgreSQL

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

Share

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

This article mainly explains "what is the role of RelationGetBufferForTuple function in PostgreSQL". The content of the explanation in this article is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "what is the role of RelationGetBufferForTuple function in PostgreSQL".

This section briefly introduces the cache-related function RelationGetBufferForTuple during PostgreSQL insertion, which returns a page that satisfies the free space > = a given size, and the corresponding buffer state of the page is pinned and holds an exclusive lock.

I. data structure

BufferDesc

Shared descriptor (status) data for shared buffer

/ * * Flags for buffer descriptors * buffer descriptor tag * * Note: TAG_VALID essentially means that there is a buffer hashtable * entry associated with the buffer's tag. * Note: TAG_VALID essentially means that there is a buffer hash table entry associated with the token of the buffer. * / / buffer header Lock # define BM_LOCKED (1U MaxHeapTupleSize) ereport (ERROR, (errcode (ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg ("row is too big: size% zu, maximum size% zu", len, MaxHeapTupleSize) / * Compute desired extra freespace due to fillfactor option * / / get reserved space / / # define RelationGetTargetPageFreeSpace (relation, defaultff)\ (BLCKSZ * (100-RelationGetFillFactor (relation, defaultff)) / 100) saveFreeSpace = RelationGetTargetPageFreeSpace (relation, HEAP_DEFAULT_FILLFACTOR) / / update operation, get the Block if (otherBuffer! = InvalidBuffer) otherBlock = BufferGetBlockNumber (otherBuffer) corresponding to the last pinned buffer; else otherBlock = InvalidBlockNumber; / * just to keep compiler quiet * / / * * We first try to put the tuple on the same page we last inserted a tuple * on, as cached in the BulkInsertState or relcache entry. If that * doesn't work, we ask the Free Space Map to locate a suitable page. * Since the FSM's info might be out of date, we have to be prepared to * loop around and retry multiple times. To insure this isn't an infinite * loop, we must update the FSM with the correct amount of free space on * each page that proves not to be suitable. If the FSM has no record of * a page with enough free space, we give up and extend the relation. * first try to put the tuple on the page that was last inserted into the tuple, such as the BulkInsertState or relcache entry. * if it cannot be found, then we use FSM to locate the appropriate page. * because the FSM information may be out of date, you have to loop and try many times. * (to ensure that this is not an infinite loop, you must update the unreliable FSM with the correct page free space information) * if the message in FSM indicates that no page has free space, abandon and extend relation. * When use_fsm is false, we either put the tuple onto the existing target * page or extend the relation. * if use_fsm is F, we can either put the tuple on the existing target page or extend relation. * / if (len + saveFreeSpace > MaxHeapTupleSize) {/ / if the required size + reserved space is greater than the maximum Tuple size that can be accommodated, do not use FSM, expand and then try / * can't fit, don't bother asking FSM * / targetBlock = InvalidBlockNumber; use_fsm = false } else if (bistate & & bistate- > current_buf! = InvalidBuffer) / / BulkInsert mode targetBlock = BufferGetBlockNumber (bistate- > current_buf); else targetBlock = RelationGetTargetBlock (relation); / / normal Insert mode if (targetBlock = = InvalidBlockNumber & & use_fsm) {/ / has not found a suitable BlockNumber yet and needs to use FSM / * We have no cached target page, so ask the FSM for an initial * target. * without caching the target page, use FSM to obtain the initial target page * / / use FSM to apply for free space = len + saveFreeSpace block targetBlock = GetPageWithFreeSpace (relation, len + saveFreeSpace); / * If the FSM knows nothing of the rel, try the last page before we * give up and extend. This avoids one-tuple-per-page syndrome during * bootstrapping or in a recently-started system. * if FSM knows nothing about rel, try the last page before giving up and extending it. * this avoids a tuple-by-page situation when bootstrapping or the system has recently been started. * / / cannot apply, use the last block, otherwise extend or discard if (targetBlock = = InvalidBlockNumber) {BlockNumber nblocks = RelationGetNumberOfBlocks (relation); if (nblocks > 0) targetBlock = nblocks-1 }} loop: while (targetBlock! = InvalidBlockNumber) {/ /-cycle until the block number of the inserted data is successfully obtained / * * Read and exclusive-lock the target block, as well as the other * block if one was given, taking suitable care with lock ordering and * the possibility they are the same block. * read and exclusively lock the target block, and given another fast (if given), you need to pay attention to the order of locks * and whether they are the same block. * If the page-level all-visible flag is set, caller will need to * clear both that and the corresponding visibility map bit. However, * by the time we return, we'll have x-locked the buffer, and we don't * want to do any I, O while in that state. So we check the bit here * before taking the lock, and pin the page if it appears necessary. * Checking without the lock creates a risk of getting the wrong * answer, so we'll have to recheck after acquiring the lock. * if a block-level all-visible flag is set, the caller needs to clear the block's tag and the corresponding vm tag. * however, on return, we will hold the exclusive lock of buffer, and we do not want to perform the IWeiO operation in this case. * therefore, we check the flag bits before getting the lock, and if it seems necessary, pin page. * there will be an error in performing the check without holding the lock, so we will have to re-perform the check after acquiring the lock. * / if (otherBuffer = = InvalidBuffer) {/ /-non-Update operation / * easy case * / / this case is relatively simple / / get Buffer buffer = ReadBufferBI (relation, targetBlock, bistate) If (PageIsAllVisible (BufferGetPage (buffer) / / if Page is visible, put Page Pin in memory (Pin means fixed / retained) visibilitymap_pin (relation, targetBlock, vmbuffer); LockBuffer (buffer, BUFFER_LOCK_EXCLUSIVE) / / Lock buffer} else if (otherBlock = = targetBlock) {/ /-Update operation. The new record is in the same Block as the original record / / this is also relatively simple / * also easy case * / buffer = otherBuffer If (PageIsAllVisible (BufferGetPage (buffer) visibilitymap_pin (relation, targetBlock, vmbuffer); LockBuffer (buffer, BUFFER_LOCK_EXCLUSIVE);} else if (otherBlock)

< targetBlock) { //----------- Update操作,原记录所在的Block < 新记录的Block /* lock other buffer first */ //首先锁定otherBlock buffer = ReadBuffer(relation, targetBlock); if (PageIsAllVisible(BufferGetPage(buffer))) visibilitymap_pin(relation, targetBlock, vmbuffer); //优先锁定BlockNumber小的那个 LockBuffer(otherBuffer, BUFFER_LOCK_EXCLUSIVE); LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE); } else { //------------ Update操作,原记录所在的Block >

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