postgres.git / summary / log / commit / refs
commit 0e2fb2c8c307aaee5ab47aa92055b53ca146706b
Author: Michael Paquier <michael@paquier.xyz>
Date: Wed Aug 05 07:55:26 2026 +0000
Initialize read stream before fetching metapage in hash bulk-deletion
hashbulkdelete() fetched the relcache's cached hash metapage before
calling read_stream_begin_relation(). During the read stream
initialization, relation lookups may process pending relcache
invalidation messages, which could cause the cached metapage to be
invalidated before the read stream uses it, leading to the failure of a
VACUUM bulk-deletion for a hash index.
This commit reworks the order of hashbulkdelete() so as its read stream
is initialized before fetching the cached metapage, so as pending
invalidation messages do not interfere with the relation scan.
Issue introduced by bfa3c4f106b1.
Author: Mikhail Nikalayeu <mihailnikalayeu@gmail.com>
Reviewed-by: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Nazir Bilal Yavuz <byavuz81@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Discussion: https://postgr.es/m/CADzfLwVEJ2_7ioX3ZSB1P7qXW40ghUy_ZCzeFvhDLoa_3Muztg@mail.gmail.com
Backpatch-through: 19
src/backend/access/hash/hash.c | 28 +++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c
index 8d8cd30dc38..b2e34d2d45e 100644
--- a/src/backend/access/hash/hash.c
+++ b/src/backend/access/hash/hash.c
@@ -515,6 +515,21 @@ hashbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
tuples_removed = 0;
num_index_tuples = 0;
+ /*
+ * Set up the streaming read before fetching the cached metapage as read
+ * stream initialization may process relcache invalidation messages,
+ * invalidating the cached metapage. It is safe to use batchmode as
+ * hash_bulkdelete_read_stream_cb takes no locks.
+ */
+ stream = read_stream_begin_relation(READ_STREAM_MAINTENANCE |
+ READ_STREAM_USE_BATCHING,
+ info->strategy,
+ rel,
+ MAIN_FORKNUM,
+ hash_bulkdelete_read_stream_cb,
+ &stream_private,
+ 0);
+
/*
* We need a copy of the metapage so that we can use its hashm_spares[]
* values to compute bucket page addresses, but a cached copy should be
@@ -536,19 +551,6 @@ hashbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
stream_private.next_bucket = cur_bucket;
stream_private.max_bucket = cur_maxbucket;
- /*
- * It is safe to use batchmode as hash_bulkdelete_read_stream_cb takes no
- * locks.
- */
- stream = read_stream_begin_relation(READ_STREAM_MAINTENANCE |
- READ_STREAM_USE_BATCHING,
- info->strategy,
- rel,
- MAIN_FORKNUM,
- hash_bulkdelete_read_stream_cb,
- &stream_private,
- 0);
-
bucket_loop:
while (cur_bucket <= cur_maxbucket)
{
[parent: c5e11de2f378]