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

Commit898a7bd

Browse files
committed
Bug fixes for GiST crash recovery.
- add forgotten check of lsn for insert completion- remove level of pages: hard to check in recovery- some cleanups
1 parent7a30b1f commit898a7bd

File tree

6 files changed

+95
-65
lines changed

6 files changed

+95
-65
lines changed

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

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.124 2005/06/29 14:06:14 teodor Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.125 2005/06/30 17:52:13 teodor Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -587,7 +587,7 @@ gistfindleaf(GISTInsertState *state, GISTSTATE *giststate)
587587
* Should have the same interface as XLogReadBuffer
588588
*/
589589
staticBuffer
590-
gistReadAndLockBuffer(boolunused,Relationr,BlockNumberblkno ) {
590+
gistReadAndLockBuffer(Relationr,BlockNumberblkno ) {
591591
Bufferbuffer=ReadBuffer(r,blkno );
592592
LockBuffer(buffer,GIST_SHARE );
593593
returnbuffer;
@@ -601,7 +601,7 @@ gistReadAndLockBuffer( bool unused, Relation r, BlockNumber blkno ) {
601601
* returns from the begining of closest parent;
602602
*/
603603
GISTInsertStack*
604-
gistFindPath(Relationr,BlockNumberchild,Buffer (*myReadBuffer)(bool,Relation,BlockNumber) ) {
604+
gistFindPath(Relationr,BlockNumberchild,Buffer (*myReadBuffer)(Relation,BlockNumber) ) {
605605
Pagepage;
606606
Bufferbuffer;
607607
OffsetNumberi,maxoff;
@@ -614,9 +614,15 @@ gistFindPath( Relation r, BlockNumber child, Buffer (*myReadBuffer)(bool, Relat
614614
top->blkno=GIST_ROOT_BLKNO;
615615

616616
while(top&&top->blkno!=child ) {
617-
buffer=myReadBuffer(false,r,top->blkno);/* buffer locked */
617+
buffer=myReadBuffer(r,top->blkno);/* buffer locked */
618618
page= (Page)BufferGetPage(buffer );
619-
Assert( !GistPageIsLeaf(page) );
619+
620+
if (GistPageIsLeaf(page) ) {
621+
/* we can safety go away, follows only leaf pages */
622+
LockBuffer(buffer,GIST_UNLOCK );
623+
ReleaseBuffer(buffer );
624+
returnNULL;
625+
}
620626

621627
top->lsn=PageGetLSN(page);
622628

@@ -662,7 +668,7 @@ gistFindPath( Relation r, BlockNumber child, Buffer (*myReadBuffer)(bool, Relat
662668
LockBuffer(buffer,GIST_UNLOCK );
663669
ReleaseBuffer(buffer );
664670
returntop;
665-
}elseif (GistPageGetOpaque(page)->level>0 ) {
671+
}else {
666672
/* Install next inner page to the end of stack */
667673
ptr= (GISTInsertStack*)palloc0(sizeof(GISTInsertStack) );
668674
ptr->blkno=blkno;
@@ -855,11 +861,9 @@ gistSplit(Relation r,
855861
OffsetNumber*realoffset;
856862
IndexTuple*cleaneditup=itup;
857863
intlencleaneditup=*len;
858-
intlevel;
859864

860865
p= (Page)BufferGetPage(buffer);
861866
opaque=GistPageGetOpaque(p);
862-
level=opaque->level;
863867

864868
/*
865869
* The root of the tree is the first block in the relation. If we're
@@ -872,7 +876,6 @@ gistSplit(Relation r,
872876
GISTInitBuffer(leftbuf,opaque->flags&F_LEAF);
873877
lbknum=BufferGetBlockNumber(leftbuf);
874878
left= (Page)BufferGetPage(leftbuf);
875-
GistPageGetOpaque(left)->level=level;
876879
}
877880
else
878881
{
@@ -886,7 +889,6 @@ gistSplit(Relation r,
886889
GISTInitBuffer(rightbuf,opaque->flags&F_LEAF);
887890
rbknum=BufferGetBlockNumber(rightbuf);
888891
right= (Page)BufferGetPage(rightbuf);
889-
GistPageGetOpaque(right)->level=level;
890892

891893
/* generate the item array */
892894
realoffset=palloc((*len+1)*sizeof(OffsetNumber));
@@ -1068,13 +1070,10 @@ void
10681070
gistnewroot(Relationr,Bufferbuffer,IndexTuple*itup,intlen,ItemPointerkey)
10691071
{
10701072
Pagepage;
1071-
intlevel;
10721073

10731074
Assert(BufferGetBlockNumber(buffer)==GIST_ROOT_BLKNO );
10741075
page=BufferGetPage(buffer);
1075-
level=GistPageGetOpaque(page)->level;
10761076
GISTInitBuffer(buffer,0);
1077-
GistPageGetOpaque(page)->level=level+1;
10781077

10791078
gistfillbuffer(r,page,itup,len,FirstOffsetNumber);
10801079
if ( !r->rd_istemp ) {

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/gist/gistutil.c,v 1.4 2005/06/28 15:51:00 teodor Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/gist/gistutil.c,v 1.5 2005/06/30 17:52:14 teodor Exp $
1212
*-------------------------------------------------------------------------
1313
*/
1414
#include"postgres.h"
@@ -809,8 +809,6 @@ GISTInitBuffer(Buffer b, uint32 f)
809809

810810
opaque=GistPageGetOpaque(page);
811811
opaque->flags=f;
812-
opaque->nsplited=0;
813-
opaque->level=0;
814812
opaque->rightlink=InvalidBlockNumber;
815813
memset(&(opaque->nsn),0,sizeof(GistNSN) );
816814
}

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.5 2005/06/29 14:06:14 teodor Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.6 2005/06/30 17:52:14 teodor Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -60,7 +60,6 @@ gistVacuumUpdate( GistVacuum *gv, BlockNumber blkno, bool needunion ) {
6060
page= (Page)BufferGetPage(buffer);
6161
maxoff=PageGetMaxOffsetNumber(page);
6262

63-
6463
if (GistPageIsLeaf(page) ) {
6564
if (GistTuplesDeleted(page) ) {
6665
needunion=needwrite= true;

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

Lines changed: 77 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/gist/gistxlog.c,v 1.5 2005/06/28 15:51:00 teodor Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/gist/gistxlog.c,v 1.6 2005/06/30 17:52:14 teodor Exp $
1212
*-------------------------------------------------------------------------
1313
*/
1414
#include"postgres.h"
@@ -44,6 +44,7 @@ typedef struct {
4444

4545
typedefstructgistIncompleteInsert {
4646
RelFileNodenode;
47+
BlockNumberorigblkno;/* for splits */
4748
ItemPointerDatakey;
4849
intlenblk;
4950
BlockNumber*blkno;
@@ -79,6 +80,7 @@ pushIncompleteInsert(RelFileNode node, XLogRecPtr lsn, ItemPointerData key,
7980
ninsert->lenblk=lenblk;
8081
ninsert->blkno= (BlockNumber*)palloc(sizeof(BlockNumber)*ninsert->lenblk );
8182
memcpy(ninsert->blkno,blkno,sizeof(BlockNumber)*ninsert->lenblk);
83+
ninsert->origblkno=*blkno;
8284
}else {
8385
inti;
8486

@@ -87,6 +89,7 @@ pushIncompleteInsert(RelFileNode node, XLogRecPtr lsn, ItemPointerData key,
8789
ninsert->blkno= (BlockNumber*)palloc(sizeof(BlockNumber)*ninsert->lenblk );
8890
for(i=0;i<ninsert->lenblk;i++)
8991
ninsert->blkno[i]=xlinfo->page[i].header->blkno;
92+
ninsert->origblkno=xlinfo->data->origblkno;
9093
}
9194
Assert(ninsert->lenblk>0 );
9295

@@ -209,6 +212,7 @@ gistRedoEntryUpdateRecord(XLogRecPtr lsn, XLogRecord *record, bool isnewroot) {
209212

210213
PageSetLSN(page,lsn);
211214
PageSetTLI(page,ThisTimeLineID);
215+
GistPageGetOpaque(page)->rightlink=InvalidBlockNumber;
212216
LockBuffer(buffer,BUFFER_LOCK_UNLOCK);
213217
WriteBuffer(buffer);
214218

@@ -466,81 +470,98 @@ gist_form_invalid_tuple(BlockNumber blkno) {
466470
returntuple;
467471
}
468472

473+
staticBuffer
474+
gistXLogReadAndLockBuffer(Relationr,BlockNumberblkno ) {
475+
Bufferbuffer=XLogReadBuffer( false,r,blkno );
476+
if (!BufferIsValid(buffer))
477+
elog(PANIC,"gistXLogReadAndLockBuffer: block %u unfound",blkno);
478+
if (PageIsNew( (PageHeader)(BufferGetPage(buffer)) ) )
479+
elog(PANIC,"gistXLogReadAndLockBuffer: uninitialized page %u",blkno);
480+
481+
returnbuffer;
482+
}
483+
484+
469485
staticvoid
470486
gixtxlogFindPath(Relationindex,gistIncompleteInsert*insert ) {
471-
inti;
472487
GISTInsertStack*top;
473488

474489
insert->pathlen=0;
475490
insert->path=NULL;
476491

477-
for(i=0;insert->lenblk;i++) {
478-
if ( (top=gistFindPath(index,insert->blkno[i],XLogReadBuffer))!=NULL ) {
479-
GISTInsertStack*ptr=top;
480-
while(ptr) {
481-
insert->pathlen++;
482-
ptr=ptr->parent;
483-
}
492+
if ( (top=gistFindPath(index,insert->origblkno,gistXLogReadAndLockBuffer))!=NULL) {
493+
inti;
494+
GISTInsertStack*ptr=top;
495+
while(ptr) {
496+
insert->pathlen++;
497+
ptr=ptr->parent;
498+
}
484499

485-
insert->path=(BlockNumber*)palloc(sizeof(BlockNumber)*insert->pathlen );
500+
insert->path=(BlockNumber*)palloc(sizeof(BlockNumber)*insert->pathlen );
486501

487-
i=0;
488-
ptr=top;
489-
while(ptr) {
490-
insert->path[i]=ptr->blkno;
491-
i++;
492-
ptr=ptr->parent;
493-
}
494-
break;
502+
i=0;
503+
ptr=top;
504+
while(ptr) {
505+
insert->path[i]=ptr->blkno;
506+
i++;
507+
ptr=ptr->parent;
495508
}
496-
}
509+
}else
510+
elog(LOG,"gixtxlogFindPath: lost parent for block %u",insert->origblkno);
497511
}
498512

499513
staticvoid
500514
gistContinueInsert(gistIncompleteInsert*insert) {
501515
IndexTuple*itup;
502516
inti,lenitup;
503-
MemoryContextoldCxt;
504517
Relationindex;
505518

506-
oldCxt=MemoryContextSwitchTo(opCtx);
507-
508519
index=XLogOpenRelation(insert->node);
509-
if (!RelationIsValid(index))
520+
if (!RelationIsValid(index))
510521
return;
511522

512-
elog(LOG,"Detected incomplete insert into GiST index %u/%u/%u; It's desirable to vacuum or reindex index",
513-
insert->node.spcNode,insert->node.dbNode,insert->node.relNode);
514-
515523
/* needed vector itup never will be more than initial lenblkno+2,
516524
because during this processing Indextuple can be only smaller */
517525
lenitup=insert->lenblk;
518526
itup= (IndexTuple*)palloc(sizeof(IndexTuple)*(lenitup+2/*guarantee root split*/));
519527

520-
for(i=0;i<insert->lenblk;i++)
528+
for(i=0;i<insert->lenblk;i++)
521529
itup[i]=gist_form_invalid_tuple(insert->blkno[i] );
522530

523-
/* construct path */
524-
gixtxlogFindPath(index,insert );
525-
526-
if (insert->pathlen==0 ) {
527-
/*it was split root, so we should only make new root*/
531+
if (insert->origblkno==GIST_ROOT_BLKNO ) {
532+
/*it was split root, so we should only make new root.
533+
it can't be simple insert into root, look at call
534+
pushIncompleteInsert in gistRedoPageSplitRecord */
528535
Bufferbuffer=XLogReadBuffer(true,index,GIST_ROOT_BLKNO);
529536
Pagepage;
530537

531538
if (!BufferIsValid(buffer))
532539
elog(PANIC,"gistContinueInsert: root block unfound");
533540

541+
page=BufferGetPage(buffer);
542+
if (XLByteLE(insert->lsn,PageGetLSN(page))) {
543+
LockBuffer(buffer,BUFFER_LOCK_UNLOCK);
544+
ReleaseBuffer(buffer);
545+
return;
546+
}
547+
534548
GISTInitBuffer(buffer,0);
535549
page=BufferGetPage(buffer);
536550
gistfillbuffer(index,page,itup,lenitup,FirstOffsetNumber);
551+
PageSetLSN(page,insert->lsn);
552+
PageSetTLI(page,ThisTimeLineID);
537553
LockBuffer(buffer,BUFFER_LOCK_UNLOCK);
538554
WriteBuffer(buffer);
539555
}else {
540556
Buffer*buffers;
541557
Page*pages;
542558
intnumbuffer;
543-
559+
560+
/* construct path */
561+
gixtxlogFindPath(index,insert );
562+
563+
Assert(insert->pathlen>0 );
564+
544565
buffers= (Buffer*)palloc(sizeof(Buffer)* (insert->lenblk+2/*guarantee root split*/) );
545566
pages= (Page*)palloc(sizeof(Page )* (insert->lenblk+2/*guarantee root split*/) );
546567

@@ -555,6 +576,12 @@ gistContinueInsert(gistIncompleteInsert *insert) {
555576
if (PageIsNew((PageHeader)(pages[numbuffer-1])) )
556577
elog(PANIC,"gistContinueInsert: uninitialized page");
557578

579+
if (XLByteLE(insert->lsn,PageGetLSN(pages[numbuffer-1]))) {
580+
LockBuffer(buffers[numbuffer-1],BUFFER_LOCK_UNLOCK);
581+
ReleaseBuffer(buffers[numbuffer-1]);
582+
return;
583+
}
584+
558585
pituplen=PageGetMaxOffsetNumber(pages[numbuffer-1]);
559586

560587
/* remove old IndexTuples */
@@ -587,9 +614,10 @@ gistContinueInsert(gistIncompleteInsert *insert) {
587614
if (BufferGetBlockNumber(buffers[0] )==GIST_ROOT_BLKNO ) {
588615
IndexTuple*parentitup;
589616

617+
/* we split root, just copy tuples from old root to new page */
590618
parentitup=gistextractbuffer(buffers[numbuffer-1],&pituplen);
591619

592-
/*we split root, just copy tuples from old root to new page */
620+
/*sanity check */
593621
if (i+1!=insert->pathlen )
594622
elog(PANIC,"gistContinueInsert: can't restore index '%s'",
595623
RelationGetRelationName(index ));
@@ -624,14 +652,15 @@ gistContinueInsert(gistIncompleteInsert *insert) {
624652
itup[j]=gist_form_invalid_tuple(BufferGetBlockNumber(buffers[j] ) );
625653
PageSetLSN(pages[j],insert->lsn);
626654
PageSetTLI(pages[j],ThisTimeLineID);
655+
GistPageGetOpaque(pages[j])->rightlink=InvalidBlockNumber;
627656
LockBuffer(buffers[j],BUFFER_LOCK_UNLOCK);
628657
WriteBuffer(buffers[j] );
629658
}
630659
}
631660
}
632661

633-
MemoryContextSwitchTo(oldCxt);
634-
MemoryContextReset(opCtx);
662+
elog(LOG,"Detected incomplete insert into GiST index %u/%u/%u; It's desirable to vacuum or reindex index",
663+
insert->node.spcNode,insert->node.dbNode,insert->node.relNode);
635664
}
636665

637666
void
@@ -648,11 +677,22 @@ gist_xlog_startup(void) {
648677
void
649678
gist_xlog_cleanup(void) {
650679
ListCell*l;
680+
List*reverse=NIL;
681+
MemoryContextoldCxt=MemoryContextSwitchTo(insertCtx);
651682

652-
foreach(l,incomplete_inserts) {
683+
/* we should call gistContinueInsert in reverse order */
684+
685+
foreach(l,incomplete_inserts)
686+
reverse=lappend(reverse,lfirst(l));
687+
688+
MemoryContextSwitchTo(opCtx);
689+
foreach(l,reverse) {
653690
gistIncompleteInsert*insert= (gistIncompleteInsert*)lfirst(l);
654691
gistContinueInsert(insert);
692+
MemoryContextReset(opCtx);
655693
}
694+
MemoryContextSwitchTo(oldCxt);
695+
656696
MemoryContextDelete(opCtx);
657697
MemoryContextDelete(insertCtx);
658698
}

‎src/include/access/gist.h

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
1010
* Portions Copyright (c) 1994, Regents of the University of California
1111
*
12-
* $PostgreSQL: pgsql/src/include/access/gist.h,v 1.48 2005/06/27 12:45:22 teodor Exp $
12+
* $PostgreSQL: pgsql/src/include/access/gist.h,v 1.49 2005/06/30 17:52:14 teodor Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -45,13 +45,7 @@ typedef XLogRecPtr GistNSN;
4545

4646
typedefstructGISTPageOpaqueData
4747
{
48-
uint8flags;
49-
50-
/* number page to which current one is splitted in last split */
51-
uint8nsplited;
52-
53-
/* level of page, 0 - leaf */
54-
uint16level;
48+
uint32flags;/* 29 bits are unused for now */
5549
BlockNumberrightlink;
5650

5751
/* the only meaning - change this value if

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp