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

Commit579b9f9

Browse files
committed
Fix handling of all-zero pages in SP-GiST vacuum.
SP-GiST initialized an all-zeros page at vacuum, but that was notWAL-logged, which is not safe. You might get a torn page write, when it getsflushed to disk, and end-up with a half-initialized index page. To fix,leave it in the all-zeros state, and add it to the FSM. It will beinitialized when reused. Also don't set the page-deleted flag when recyclingan empty page. That was also not WAL-logged, and a torn write of that wouldcause the page to have an invalid checksum.Backpatch to 9.2, where SP-GiST indexes were added.
1 parent491c24f commit579b9f9

File tree

2 files changed

+10
-21
lines changed

2 files changed

+10
-21
lines changed

‎src/backend/access/spgist/spgvacuum.c

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -618,14 +618,10 @@ spgvacuumpage(spgBulkDeleteState *bds, BlockNumber blkno)
618618
{
619619
/*
620620
* We found an all-zero page, which could happen if the database
621-
* crashed just after extending the file.Initialize and recycle it.
621+
* crashed just after extending the file.Recycle it.
622622
*/
623-
SpGistInitBuffer(buffer,0);
624-
SpGistPageSetDeleted(page);
625-
/* We don't bother to WAL-log this action; easy to redo */
626-
MarkBufferDirty(buffer);
627623
}
628-
elseif (SpGistPageIsDeleted(page))
624+
elseif (PageIsEmpty(page))
629625
{
630626
/* nothing to do */
631627
}
@@ -651,30 +647,23 @@ spgvacuumpage(spgBulkDeleteState *bds, BlockNumber blkno)
651647
/*
652648
* The root pages must never be deleted, nor marked as available in FSM,
653649
* because we don't want them ever returned by a search for a place to put
654-
* a new tuple. Otherwise, check for empty/deletable page, and make sure
655-
*FSMknows about it.
650+
* a new tuple. Otherwise, check for empty page, and make sure the FSM
651+
* knows about it.
656652
*/
657653
if (!SpGistBlockIsRoot(blkno))
658654
{
659-
/* If page is now empty, mark it deleted */
660-
if (PageIsEmpty(page)&& !SpGistPageIsDeleted(page))
661-
{
662-
SpGistPageSetDeleted(page);
663-
/* We don't bother to WAL-log this action; easy to redo */
664-
MarkBufferDirty(buffer);
665-
}
666-
667-
if (SpGistPageIsDeleted(page))
655+
if (PageIsEmpty(page))
668656
{
669657
RecordFreeIndexPage(index,blkno);
670658
bds->stats->pages_deleted++;
671659
}
672660
else
661+
{
662+
SpGistSetLastUsedPage(index,buffer);
673663
bds->lastFilledBlock=blkno;
664+
}
674665
}
675666

676-
SpGistSetLastUsedPage(index,buffer);
677-
678667
UnlockReleaseBuffer(buffer);
679668
}
680669

‎src/include/access/spgist_private.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,14 @@ typedef SpGistPageOpaqueData *SpGistPageOpaque;
4848

4949
/* Flag bits in page special space */
5050
#defineSPGIST_META(1<<0)
51-
#defineSPGIST_DELETED(1<<1)
51+
#defineSPGIST_DELETED(1<<1)/* never set, but keep for backwards
52+
* compatibility */
5253
#defineSPGIST_LEAF(1<<2)
5354
#defineSPGIST_NULLS(1<<3)
5455

5556
#defineSpGistPageGetOpaque(page) ((SpGistPageOpaque) PageGetSpecialPointer(page))
5657
#defineSpGistPageIsMeta(page) (SpGistPageGetOpaque(page)->flags & SPGIST_META)
5758
#defineSpGistPageIsDeleted(page) (SpGistPageGetOpaque(page)->flags & SPGIST_DELETED)
58-
#defineSpGistPageSetDeleted(page) (SpGistPageGetOpaque(page)->flags |= SPGIST_DELETED)
5959
#defineSpGistPageIsLeaf(page) (SpGistPageGetOpaque(page)->flags & SPGIST_LEAF)
6060
#defineSpGistPageStoresNulls(page) (SpGistPageGetOpaque(page)->flags & SPGIST_NULLS)
6161

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp