From 389ccf54b12cf32d49222e7c2b5b6b89083b98c7 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 to prevent early reuse --- src/backend/access/gin/ginutil.c | 7 ++++++- src/backend/access/gin/ginxlog.c | 1 + src/include/access/gin_private.h | 3 +++ src/include/access/ginxlog.h | 1 + 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c index d7696a1ad0..9072ee6260 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), RecentGlobalDataXmin)) return buffer; /* OK to use */ LockBuffer(buffer, GIN_UNLOCK); 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)