Skip to content

Commit 501c7b9

Browse files
committed
Fix bug in hashbulkdelete.
Commit 6d46f47 failed to account for the possibility that hashbulkdelete() might encounter a bucket that has been split since it began scanning the bucket array. Repair. Extracted from a larger pathc by Amit Kapila; I rewrote the comment.
1 parent a256650 commit 501c7b9

File tree

1 file changed

+19
-3
lines changed

1 file changed

+19
-3
lines changed

src/backend/access/hash/hash.c

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,8 @@ hashbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
523523
orig_maxbucket = metap->hashm_maxbucket;
524524
orig_ntuples = metap->hashm_ntuples;
525525
memcpy(&local_metapage, metap, sizeof(local_metapage));
526-
_hash_relbuf(rel, metabuf);
526+
/* release the lock, but keep pin */
527+
_hash_chgbufaccess(rel, metabuf, HASH_READ, HASH_NOLOCK);
527528

528529
/* Scan the buckets that we know exist */
529530
cur_bucket = 0;
@@ -563,8 +564,23 @@ hashbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
563564
*/
564565
if (!H_BUCKET_BEING_SPLIT(bucket_opaque) &&
565566
H_NEEDS_SPLIT_CLEANUP(bucket_opaque))
567+
{
566568
split_cleanup = true;
567569

570+
/*
571+
* This bucket might have been split since we last held a lock on
572+
* the metapage. If so, hashm_maxbucket, hashm_highmask and
573+
* hashm_lowmask might be old enough to cause us to fail to remove
574+
* tuples left behind by the most recent split. To prevent that,
575+
* now that the primary page of the target bucket has been locked
576+
* (and thus can't be further split), update our cached metapage
577+
* data.
578+
*/
579+
_hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_READ);
580+
memcpy(&local_metapage, metap, sizeof(local_metapage));
581+
_hash_chgbufaccess(rel, metabuf, HASH_READ, HASH_NOLOCK);
582+
}
583+
568584
bucket_buf = buf;
569585

570586
hashbucketcleanup(rel, cur_bucket, bucket_buf, blkno, info->strategy,
@@ -581,15 +597,15 @@ hashbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
581597
}
582598

583599
/* Write-lock metapage and check for split since we started */
584-
metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_WRITE, LH_META_PAGE);
600+
_hash_chgbufaccess(rel, metabuf, HASH_NOLOCK, HASH_WRITE);
585601
metap = HashPageGetMeta(BufferGetPage(metabuf));
586602

587603
if (cur_maxbucket != metap->hashm_maxbucket)
588604
{
589605
/* There's been a split, so process the additional bucket(s) */
590606
cur_maxbucket = metap->hashm_maxbucket;
591607
memcpy(&local_metapage, metap, sizeof(local_metapage));
592-
_hash_relbuf(rel, metabuf);
608+
_hash_chgbufaccess(rel, metabuf, HASH_READ, HASH_NOLOCK);
593609
goto loop_top;
594610
}
595611

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy