From 1934325e4dd212b5c73ff659fdba83d94a7a5d41 Mon Sep 17 00:00:00 2001 From: Peter Geoghegan Date: Mon, 29 Nov 2021 12:40:43 -0800 Subject: [PATCH v1] Deprecate the term "super-exclusive lock". --- src/include/access/heapam_xlog.h | 4 ++-- src/backend/access/gin/README | 2 +- src/backend/access/heap/heapam.c | 4 ++-- src/backend/access/heap/pruneheap.c | 2 +- src/backend/access/nbtree/README | 34 ++++++++++++++--------------- src/backend/access/nbtree/nbtpage.c | 5 ++--- src/backend/access/nbtree/nbtree.c | 6 ++--- src/backend/storage/page/bufpage.c | 8 +++---- 8 files changed, 32 insertions(+), 33 deletions(-) diff --git a/src/include/access/heapam_xlog.h b/src/include/access/heapam_xlog.h index 27db48184..84d7f101d 100644 --- a/src/include/access/heapam_xlog.h +++ b/src/include/access/heapam_xlog.h @@ -238,7 +238,7 @@ typedef struct xl_heap_update * Note that nunused is not explicitly stored, but may be found by reference * to the total record length. * - * Requires a super-exclusive lock. + * Acquires a full cleanup lock. */ typedef struct xl_heap_prune { @@ -254,7 +254,7 @@ typedef struct xl_heap_prune * The vacuum page record is similar to the prune record, but can only mark * already dead items as unused * - * Used by heap vacuuming only. Does not require a super-exclusive lock. + * Used by heap vacuuming only. Acquires an ordinary exclusive lock only. */ typedef struct xl_heap_vacuum { diff --git a/src/backend/access/gin/README b/src/backend/access/gin/README index 41d4e1e8a..b08073162 100644 --- a/src/backend/access/gin/README +++ b/src/backend/access/gin/README @@ -396,7 +396,7 @@ leafs. If first stage detects at least one empty page, then at the second stage ginScanToDelete() deletes empty pages. ginScanToDelete() traverses the whole tree in depth-first manner. It starts -from the super-exclusive lock on the tree root. This lock prevents all the +from the full cleanup lock on the tree root. This lock prevents all the concurrent insertions into this tree while we're deleting pages. However, there are still might be some in-progress readers, who traversed root before we locked it. diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 17afe1ea4..0b4a46b31 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -8448,7 +8448,7 @@ ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_changed, /* * Handles XLOG_HEAP2_PRUNE record type. * - * Acquires a super-exclusive lock. + * Acquires a full cleanup lock. */ static void heap_xlog_prune(XLogReaderState *record) @@ -8534,7 +8534,7 @@ heap_xlog_prune(XLogReaderState *record) /* * Handles XLOG_HEAP2_VACUUM record type. * - * Acquires an exclusive lock only. + * Acquires an ordinary exclusive lock only. */ static void heap_xlog_vacuum(XLogReaderState *record) diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c index 5c0b60319..522a00af6 100644 --- a/src/backend/access/heap/pruneheap.c +++ b/src/backend/access/heap/pruneheap.c @@ -844,7 +844,7 @@ heap_prune_record_unused(PruneState *prstate, OffsetNumber offnum) /* * Perform the actual page changes needed by heap_page_prune. - * It is expected that the caller has a super-exclusive lock on the + * It is expected that the caller has a full cleanup lock on the * buffer. */ void diff --git a/src/backend/access/nbtree/README b/src/backend/access/nbtree/README index 2a7332d07..f964e2d9d 100644 --- a/src/backend/access/nbtree/README +++ b/src/backend/access/nbtree/README @@ -166,14 +166,14 @@ that the incoming item doesn't fit on the split page where it needs to go! Deleting index tuples during VACUUM ----------------------------------- -Before deleting a leaf item, we get a super-exclusive lock on the target +Before deleting a leaf item, we get a full cleanup lock on the target page, so that no other backend has a pin on the page when the deletion starts. This is not necessary for correctness in terms of the btree index operations themselves; as explained above, index scans logically stop "between" pages and so can't lose their place. The reason we do it is to provide an interlock between VACUUM and indexscans. Since VACUUM deletes index entries before reclaiming heap tuple line pointers, the -super-exclusive lock guarantees that VACUUM can't reclaim for re-use a +cleanup lock guarantees that VACUUM can't reclaim for re-use a line pointer that an indexscanning process might be about to visit. This guarantee works only for simple indexscans that visit the heap in sync with the index scan, not for bitmap scans. We only need the guarantee @@ -185,15 +185,15 @@ factors will not hold the pin after the page contents are read. The current reasons for exceptions, where a pin is still needed, are if the index is not WAL-logged or if the scan is an index-only scan. If later work allows the pin to be dropped for all cases we will be able to -simplify the vacuum code, since the concept of a super-exclusive lock -for btree indexes will no longer be needed. +simplify the vacuum code, since the concept of a cleanup lock for btree +indexes will no longer be needed. Because a pin is not always held, and a page can be split even while someone does hold a pin on it, it is possible that an indexscan will return items that are no longer stored on the page it has a pin on, but rather somewhere to the right of that page. To ensure that VACUUM can't prematurely remove such heap tuples, we require btbulkdelete to obtain a -super-exclusive lock on every leaf page in the index, even pages that +full cleanup lock on every leaf page in the index, even pages that don't contain any deletable tuples. Any scan which could yield incorrect results if the tuple at a TID matching the scan's range and filter conditions were replaced by a different tuple while the scan is in @@ -519,12 +519,12 @@ groups of dead TIDs from posting list tuples (without the situation ever being allowed to get out of hand). It's sufficient to have an exclusive lock on the index page, not a -super-exclusive lock, to do deletion of LP_DEAD items. It might seem +full cleanup lock, to do deletion of LP_DEAD items. It might seem that this breaks the interlock between VACUUM and indexscans, but that is not so: as long as an indexscanning process has a pin on the page where the index item used to be, VACUUM cannot complete its btbulkdelete scan and so cannot remove the heap tuple. This is another reason why -btbulkdelete has to get a super-exclusive lock on every leaf page, not only +btbulkdelete has to get a full cleanup lock on every leaf page, not only the ones where it actually sees items to delete. LP_DEAD setting by index scans cannot be sure that a TID whose index tuple @@ -734,16 +734,16 @@ changes state into a normally running server. The interlocking required to avoid returning incorrect results from non-MVCC scans is not required on standby nodes. We still get a -super-exclusive lock ("cleanup lock") when replaying VACUUM records -during recovery, but recovery does not need to lock every leaf page -(only those leaf pages that have items to delete). That is safe because -HeapTupleSatisfiesUpdate(), HeapTupleSatisfiesSelf(), -HeapTupleSatisfiesDirty() and HeapTupleSatisfiesVacuum() are only ever -used during write transactions, which cannot exist on the standby. MVCC -scans are already protected by definition, so HeapTupleSatisfiesMVCC() -is not a problem. The optimizer looks at the boundaries of value ranges -using HeapTupleSatisfiesNonVacuumable() with an index-only scan, which -is also safe. That leaves concern only for HeapTupleSatisfiesToast(). +full cleanup lock when replaying VACUUM records during recovery, but +recovery does not need to lock every leaf page (only those leaf pages +that have items to delete). That's safe, since HeapTupleSatisfiesUpdate(), +HeapTupleSatisfiesSelf(), HeapTupleSatisfiesDirty() and +HeapTupleSatisfiesVacuum() are only ever used during write transactions, +which cannot exist on the standby. MVCC scans are already protected by +definition, so HeapTupleSatisfiesMVCC() is not a problem. The optimizer +looks at the boundaries of value ranges using +HeapTupleSatisfiesNonVacuumable() with an index-only scan, which is also +safe. That leaves concern only for HeapTupleSatisfiesToast(). HeapTupleSatisfiesToast() doesn't use MVCC semantics, though that's because it doesn't need to - if the main heap row is visible then the diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c index 5bc7c3616..0aea476b8 100644 --- a/src/backend/access/nbtree/nbtpage.c +++ b/src/backend/access/nbtree/nbtpage.c @@ -1115,8 +1115,7 @@ _bt_conditionallockbuf(Relation rel, Buffer buf) } /* - * _bt_upgradelockbufcleanup() -- upgrade lock to super-exclusive/cleanup - * lock. + * _bt_upgradelockbufcleanup() -- upgrade lock to a full cleanup lock. */ void _bt_upgradelockbufcleanup(Relation rel, Buffer buf) @@ -1147,7 +1146,7 @@ _bt_pageinit(Page page, Size size) /* * Delete item(s) from a btree leaf page during VACUUM. * - * This routine assumes that the caller has a super-exclusive write lock on + * This routine assumes that the caller already has a full cleanup lock on * the buffer. Also, the given deletable and updatable arrays *must* be * sorted in ascending order. * diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index bd6d6b1cc..dfce06dc4 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -1161,9 +1161,9 @@ backtrack: nhtidslive; /* - * Trade in the initial read lock for a super-exclusive write lock on - * this page. We must get such a lock on every leaf page over the - * course of the vacuum scan, whether or not it actually contains any + * Trade in the initial read lock for a full cleanup lock on this + * page. We must get such a lock on every leaf page over the course + * of the vacuum scan, whether or not it actually contains any * deletable tuples --- see nbtree/README. */ _bt_upgradelockbufcleanup(rel, buf); diff --git a/src/backend/storage/page/bufpage.c b/src/backend/storage/page/bufpage.c index 82ca91f59..a5c94b0a7 100644 --- a/src/backend/storage/page/bufpage.c +++ b/src/backend/storage/page/bufpage.c @@ -701,7 +701,7 @@ compactify_tuples(itemIdCompact itemidbase, int nitems, Page page, bool presorte * there is, in general, a good chance that even large groups of unused line * pointers that we see here will be recycled quickly. * - * Caller had better have a super-exclusive lock on page's buffer. As a side + * Caller had better have a full cleanup lock on page's buffer. As a side * effect the page's PD_HAS_FREE_LINES hint bit will be set or unset as * needed. */ @@ -820,9 +820,9 @@ PageRepairFragmentation(Page page) * arbitrary, but it seems like a good idea to avoid leaving a PageIsEmpty() * page behind. * - * Caller can have either an exclusive lock or a super-exclusive lock on - * page's buffer. The page's PD_HAS_FREE_LINES hint bit will be set or unset - * based on whether or not we leave behind any remaining LP_UNUSED items. + * Caller can have either an exclusive lock or a full cleanup lock on page's + * buffer. The page's PD_HAS_FREE_LINES hint bit will be set or unset based + * on whether or not we leave behind any remaining LP_UNUSED items. */ void PageTruncateLinePointerArray(Page page) -- 2.30.2