Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit e2e992c

Browse filesBrowse files
committed
Refactor checks for deleted GiST pages.
The explicit check in gistScanPage() isn't currently really necessary, as a deleted page is always empty, so the loop would fall through without doing anything, anyway. But it's a marginal optimization, and it gives a nice place to attach a comment to explain how it works. Backpatch to v12, where GiST page deletion was introduced. Reviewed-by: Andrey Borodin Discussion: https://www.postgresql.org/message-id/835A15A5-F1B4-4446-A711-BF48357EB602%40yandex-team.ru
1 parent bfa4263 commit e2e992c
Copy full SHA for e2e992c

File tree

2 files changed

+29
-25
lines changed
Filter options

2 files changed

+29
-25
lines changed

‎src/backend/access/gist/gist.c

Copy file name to clipboardExpand all lines: src/backend/access/gist/gist.c
+15-25Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -709,14 +709,15 @@ gistdoinsert(Relation r, IndexTuple itup, Size freespace,
709709
continue;
710710
}
711711

712-
if (stack->blkno != GIST_ROOT_BLKNO &&
713-
stack->parent->lsn < GistPageGetNSN(stack->page))
712+
if ((stack->blkno != GIST_ROOT_BLKNO &&
713+
stack->parent->lsn < GistPageGetNSN(stack->page)) ||
714+
GistPageIsDeleted(stack->page))
714715
{
715716
/*
716-
* Concurrent split detected. There's no guarantee that the
717-
* downlink for this page is consistent with the tuple we're
718-
* inserting anymore, so go back to parent and rechoose the best
719-
* child.
717+
* Concurrent split or page deletion detected. There's no
718+
* guarantee that the downlink for this page is consistent with
719+
* the tuple we're inserting anymore, so go back to parent and
720+
* rechoose the best child.
720721
*/
721722
UnlockReleaseBuffer(stack->buffer);
722723
xlocked = false;
@@ -735,9 +736,6 @@ gistdoinsert(Relation r, IndexTuple itup, Size freespace,
735736
GISTInsertStack *item;
736737
OffsetNumber downlinkoffnum;
737738

738-
/* currently, internal pages are never deleted */
739-
Assert(!GistPageIsDeleted(stack->page));
740-
741739
downlinkoffnum = gistchoose(state.r, stack->page, itup, giststate);
742740
iid = PageGetItemId(stack->page, downlinkoffnum);
743741
idxtuple = (IndexTuple) PageGetItem(stack->page, iid);
@@ -858,12 +856,13 @@ gistdoinsert(Relation r, IndexTuple itup, Size freespace,
858856
* leaf/inner is enough to recognize split for root
859857
*/
860858
}
861-
else if (GistFollowRight(stack->page) ||
862-
stack->parent->lsn < GistPageGetNSN(stack->page))
859+
else if ((GistFollowRight(stack->page) ||
860+
stack->parent->lsn < GistPageGetNSN(stack->page)) &&
861+
GistPageIsDeleted(stack->page))
863862
{
864863
/*
865-
* The page was split while we momentarily unlocked the
866-
* page. Go back to parent.
864+
* The page was split or deleted while we momentarily
865+
* unlocked the page. Go back to parent.
867866
*/
868867
UnlockReleaseBuffer(stack->buffer);
869868
xlocked = false;
@@ -872,18 +871,6 @@ gistdoinsert(Relation r, IndexTuple itup, Size freespace,
872871
}
873872
}
874873

875-
/*
876-
* The page might have been deleted after we scanned the parent
877-
* and saw the downlink.
878-
*/
879-
if (GistPageIsDeleted(stack->page))
880-
{
881-
UnlockReleaseBuffer(stack->buffer);
882-
xlocked = false;
883-
state.stack = stack = stack->parent;
884-
continue;
885-
}
886-
887874
/* now state.stack->(page, buffer and blkno) points to leaf page */
888875

889876
gistinserttuple(&state, stack, giststate, itup,
@@ -947,6 +934,9 @@ gistFindPath(Relation r, BlockNumber child, OffsetNumber *downlinkoffnum)
947934
break;
948935
}
949936

937+
/* currently, internal pages are never deleted */
938+
Assert(!GistPageIsDeleted(page));
939+
950940
top->lsn = BufferGetLSNAtomic(buffer);
951941

952942
/*

‎src/backend/access/gist/gistget.c

Copy file name to clipboardExpand all lines: src/backend/access/gist/gistget.c
+14Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,20 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
377377
MemoryContextSwitchTo(oldcxt);
378378
}
379379

380+
/*
381+
* Check if the page was deleted after we saw the downlink. There's
382+
* nothing of interest on a deleted page. Note that we must do this
383+
* after checking the NSN for concurrent splits! It's possible that
384+
* the page originally contained some tuples that are visible to us,
385+
* but was split so that all the visible tuples were moved to another
386+
* page, and then this page was deleted.
387+
*/
388+
if (GistPageIsDeleted(page))
389+
{
390+
UnlockReleaseBuffer(buffer);
391+
return;
392+
}
393+
380394
so->nPageData = so->curPageData = 0;
381395
scan->xs_hitup = NULL; /* might point into pageDataCxt */
382396
if (so->pageDataCxt)

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.