From 0560b46f96e82c7082b8fcf434a3c6c9f46a94b8 Mon Sep 17 00:00:00 2001 From: Andrey Date: Mon, 10 Dec 2018 18:49:47 +0500 Subject: [PATCH] Stamp deleted GIN page with xid v3 --- src/backend/access/gin/ginutil.c | 7 ++++++- src/backend/access/gin/ginvacuum.c | 7 ++++++- src/backend/access/gin/ginxlog.c | 1 + src/include/access/gin_private.h | 3 +++ src/include/access/ginxlog.h | 1 + 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c index d7696a1ad0..5ce39d821b 100644 --- a/src/backend/access/gin/ginutil.c +++ b/src/backend/access/gin/ginutil.c @@ -314,7 +314,12 @@ GinNewBuffer(Relation index) if (PageIsNew(page)) return buffer; /* OK to use, if never initialized */ - if (GinPageIsDeleted(page)) + /* + * We should not reuse page until every transaction started before + * deletion is over + */ + if (GinPageIsDeleted(page) + && TransactionIdPrecedes(GinPageGetDeleteXid(page), RecentGlobalXmin)) return buffer; /* OK to use */ LockBuffer(buffer, GIN_UNLOCK); diff --git a/src/backend/access/gin/ginvacuum.c b/src/backend/access/gin/ginvacuum.c index 3104bc12b6..75dc03f495 100644 --- a/src/backend/access/gin/ginvacuum.c +++ b/src/backend/access/gin/ginvacuum.c @@ -16,6 +16,7 @@ #include "access/gin_private.h" #include "access/ginxlog.h" +#include "access/transam.h" #include "access/xloginsert.h" #include "commands/vacuum.h" #include "miscadmin.h" @@ -157,6 +158,9 @@ ginDeletePage(GinVacuumState *gvs, BlockNumber deleteBlkno, BlockNumber leftBlkn page = BufferGetPage(dBuffer); rightlink = GinPageGetOpaque(page)->rightlink; + /* for each deleted page we remember last xid which could knew it's address */ + GinPageSetDeleteXid(page, ReadNewTransactionId()); + /* * Any insert which would have gone on the leaf block will now go to its * right sibling. @@ -213,6 +217,7 @@ ginDeletePage(GinVacuumState *gvs, BlockNumber deleteBlkno, BlockNumber leftBlkn data.parentOffset = myoff; data.rightLink = GinPageGetOpaque(page)->rightlink; + data.deleteXid = GinPageGetDeleteXid(page); XLogRegisterData((char *) &data, sizeof(ginxlogDeletePage)); @@ -742,7 +747,7 @@ ginvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats) LockBuffer(buffer, GIN_SHARE); page = (Page) BufferGetPage(buffer); - if (PageIsNew(page) || GinPageIsDeleted(page)) + if (PageIsNew(page) || (GinPageIsDeleted(page) && TransactionIdPrecedes(GinPageGetDeleteXid(page), RecentGlobalXmin))) { Assert(blkno != GIN_ROOT_BLKNO); RecordFreeIndexPage(index, blkno); diff --git a/src/backend/access/gin/ginxlog.c b/src/backend/access/gin/ginxlog.c index 7701a2d6bf..7821f69077 100644 --- a/src/backend/access/gin/ginxlog.c +++ b/src/backend/access/gin/ginxlog.c @@ -518,6 +518,7 @@ ginRedoDeletePage(XLogReaderState *record) page = BufferGetPage(dbuffer); Assert(GinPageIsData(page)); GinPageGetOpaque(page)->flags = GIN_DELETED; + GinPageSetDeleteXid(page, data->deleteXid); PageSetLSN(page, lsn); MarkBufferDirty(dbuffer); } diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h index 81bf8734ce..83d2621488 100644 --- a/src/include/access/gin_private.h +++ b/src/include/access/gin_private.h @@ -44,6 +44,9 @@ typedef struct GinOptions #define GIN_SHARE BUFFER_LOCK_SHARE #define GIN_EXCLUSIVE BUFFER_LOCK_EXCLUSIVE +#define GinPageGetDeleteXid(page) ( ((PageHeader) (page))->pd_prune_xid ) +#define GinPageSetDeleteXid(page, val) ( ((PageHeader) (page))->pd_prune_xid = val) + /* * GinState: working data structure describing the index being worked on diff --git a/src/include/access/ginxlog.h b/src/include/access/ginxlog.h index 64a3c9e18b..d7f44d6b83 100644 --- a/src/include/access/ginxlog.h +++ b/src/include/access/ginxlog.h @@ -158,6 +158,7 @@ typedef struct ginxlogDeletePage { OffsetNumber parentOffset; BlockNumber rightLink; + TransactionId deleteXid; /* last Xid which could see page in scan */ } ginxlogDeletePage; #define XLOG_GIN_UPDATE_META_PAGE 0x60 -- 2.17.2 (Apple Git-113)