Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

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

Sign up
Appearance settings

Commit89911b3

Browse files
committed
Fix GiST buffering build bug, which caused "failed to re-find parent" errors.
We use a hash table to track the parents of inner pages, but when insertingto a leaf page, the caller of gistbufferinginserttuples() must pass acorrect block number of the leaf's parent page. Before gistProcessItup()descends to a child page, it checks if the downlink needs to be adjusted toaccommodate the new tuple, and updates the downlink if necessary. However,updating the downlink might require splitting the page, which might move thedownlink to a page to the right. gistProcessItup() doesn't realize that, sowhen it descends to the leaf page, it might pass an out-of-date parent blocknumber as a result. Fix that by returning the block a tuple was inserted tofrom gistbufferinginserttuples().This fixes the bug reported by Zdeněk Jílovec.
1 parentde3773d commit89911b3

File tree

3 files changed

+41
-14
lines changed

3 files changed

+41
-14
lines changed

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

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -148,16 +148,22 @@ gistinsert(PG_FUNCTION_ARGS)
148148
* pages are released; note that new tuple(s) are *not* on the root page
149149
* but in one of the new child pages.
150150
*
151+
* If 'newblkno' is not NULL, returns the block number of page the first
152+
* new/updated tuple was inserted to. Usually it's the given page, but could
153+
* be its right sibling if the page was split.
154+
*
151155
* Returns 'true' if the page was split, 'false' otherwise.
152156
*/
153157
bool
154158
gistplacetopage(Relationrel,Sizefreespace,GISTSTATE*giststate,
155159
Bufferbuffer,
156160
IndexTuple*itup,intntup,OffsetNumberoldoffnum,
161+
BlockNumber*newblkno,
157162
Bufferleftchildbuf,
158163
List**splitinfo,
159164
boolmarkfollowright)
160165
{
166+
BlockNumberblkno=BufferGetBlockNumber(buffer);
161167
Pagepage=BufferGetPage(buffer);
162168
boolis_leaf= (GistPageIsLeaf(page)) ? true : false;
163169
XLogRecPtrrecptr;
@@ -199,7 +205,6 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
199205
BlockNumberoldrlink=InvalidBlockNumber;
200206
GistNSNoldnsn=0;
201207
SplitedPageLayoutrootpg;
202-
BlockNumberblkno=BufferGetBlockNumber(buffer);
203208
boolis_rootsplit;
204209

205210
is_rootsplit= (blkno==GIST_ROOT_BLKNO);
@@ -319,9 +324,19 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
319324

320325
for (i=0;i<ptr->block.num;i++)
321326
{
322-
if (PageAddItem(ptr->page, (Item)data,IndexTupleSize((IndexTuple)data),i+FirstOffsetNumber, false, false)==InvalidOffsetNumber)
327+
IndexTuplethistup= (IndexTuple)data;
328+
329+
if (PageAddItem(ptr->page, (Item)data,IndexTupleSize(thistup),i+FirstOffsetNumber, false, false)==InvalidOffsetNumber)
323330
elog(ERROR,"failed to add item to index page in \"%s\"",RelationGetRelationName(rel));
324-
data+=IndexTupleSize((IndexTuple)data);
331+
332+
/*
333+
* If this is the first inserted/updated tuple, let the caller
334+
* know which page it landed on.
335+
*/
336+
if (newblkno&&ItemPointerEquals(&thistup->t_tid,&(*itup)->t_tid))
337+
*newblkno=ptr->block.blkno;
338+
339+
data+=IndexTupleSize(thistup);
325340
}
326341

327342
/* Set up rightlinks */
@@ -436,6 +451,9 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
436451
recptr=GetXLogRecPtrForTemp();
437452
PageSetLSN(page,recptr);
438453
}
454+
455+
if (newblkno)
456+
*newblkno=blkno;
439457
}
440458

441459
/*
@@ -1074,9 +1092,9 @@ gistinserttuple(GISTInsertState *state, GISTInsertStack *stack,
10741092
* is kept pinned.
10751093
*- Lock and pin on 'rightchild' are always released.
10761094
*
1077-
* Returns 'true' if the page had to be split. Note that if the pagehad
1078-
*besplit, the inserted/updated might've been inserted to a right sibling
1079-
* of stack->buffer instead of stack->buffer itself.
1095+
* Returns 'true' if the page had to be split. Note that if the pagewas
1096+
* split, the inserted/updatedtuplesmight've been inserted to a right
1097+
*siblingof stack->buffer instead of stack->buffer itself.
10801098
*/
10811099
staticbool
10821100
gistinserttuples(GISTInsertState*state,GISTInsertStack*stack,
@@ -1091,7 +1109,8 @@ gistinserttuples(GISTInsertState *state, GISTInsertStack *stack,
10911109
/* Insert the tuple(s) to the page, splitting the page if necessary */
10921110
is_split=gistplacetopage(state->r,state->freespace,giststate,
10931111
stack->buffer,
1094-
tuples,ntup,oldoffnum,
1112+
tuples,ntup,
1113+
oldoffnum,NULL,
10951114
leftchild,
10961115
&splitinfo,
10971116
true);

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

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ static void gistBufferingBuildInsert(GISTBuildState *buildstate,
8585
IndexTupleitup);
8686
staticboolgistProcessItup(GISTBuildState*buildstate,IndexTupleitup,
8787
BlockNumberstartblkno,intstartlevel);
88-
staticvoidgistbufferinginserttuples(GISTBuildState*buildstate,
88+
staticBlockNumbergistbufferinginserttuples(GISTBuildState*buildstate,
8989
Bufferbuffer,intlevel,
9090
IndexTuple*itup,intntup,OffsetNumberoldoffnum,
9191
BlockNumberparentblk,OffsetNumberdownlinkoffnum);
@@ -621,9 +621,9 @@ gistProcessItup(GISTBuildState *buildstate, IndexTuple itup,
621621
newtup=gistgetadjusted(indexrel,idxtuple,itup,giststate);
622622
if (newtup)
623623
{
624-
gistbufferinginserttuples(buildstate,buffer,level,
625-
&newtup,1,childoffnum,
626-
InvalidBlockNumber,InvalidOffsetNumber);
624+
blkno=gistbufferinginserttuples(buildstate,buffer,level,
625+
&newtup,1,childoffnum,
626+
InvalidBlockNumber,InvalidOffsetNumber);
627627
/* gistbufferinginserttuples() released the buffer */
628628
}
629629
else
@@ -676,23 +676,28 @@ gistProcessItup(GISTBuildState *buildstate, IndexTuple itup,
676676
*
677677
* This is analogous with gistinserttuples() in the regular insertion code.
678678
*
679+
* Returns the block number of the page where the (first) new or updated tuple
680+
* was inserted. Usually that's the original page, but might be a sibling page
681+
* if the original page was split.
682+
*
679683
* Caller should hold a lock on 'buffer' on entry. This function will unlock
680684
* and unpin it.
681685
*/
682-
staticvoid
686+
staticBlockNumber
683687
gistbufferinginserttuples(GISTBuildState*buildstate,Bufferbuffer,intlevel,
684688
IndexTuple*itup,intntup,OffsetNumberoldoffnum,
685689
BlockNumberparentblk,OffsetNumberdownlinkoffnum)
686690
{
687691
GISTBuildBuffers*gfbb=buildstate->gfbb;
688692
List*splitinfo;
689693
boolis_split;
694+
BlockNumberplaced_to_blk=InvalidBlockNumber;
690695

691696
is_split=gistplacetopage(buildstate->indexrel,
692697
buildstate->freespace,
693698
buildstate->giststate,
694699
buffer,
695-
itup,ntup,oldoffnum,
700+
itup,ntup,oldoffnum,&placed_to_blk,
696701
InvalidBuffer,
697702
&splitinfo,
698703
false);
@@ -823,6 +828,8 @@ gistbufferinginserttuples(GISTBuildState *buildstate, Buffer buffer, int level,
823828
}
824829
else
825830
UnlockReleaseBuffer(buffer);
831+
832+
returnplaced_to_blk;
826833
}
827834

828835
/*

‎src/include/access/gist_private.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,8 @@ typedef struct
430430

431431
externboolgistplacetopage(Relationrel,Sizefreespace,GISTSTATE*giststate,
432432
Bufferbuffer,
433-
IndexTuple*itup,intntup,OffsetNumberoldoffnum,
433+
IndexTuple*itup,intntup,
434+
OffsetNumberoldoffnum,BlockNumber*newblkno,
434435
Bufferleftchildbuf,
435436
List**splitinfo,
436437
boolmarkleftchild);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp