From 5c73ae17d18a424fe63c0a1d8b674e9f22800572 Mon Sep 17 00:00:00 2001
From: Simon Riggs <simon@2ndQuadrant.com>
Date: Fri, 19 Mar 2010 10:41:22 +0000
Subject: [PATCH] Reset btpo.xact following recovery of btree delete page. Add
 btpo_xact field into WAL record and reset it from there, rather than using
 FrozenTransactionId which can lead to some corner case bugs.

Problem report and suggested route to a fix from Heikki, details by me.
---
 src/backend/access/nbtree/nbtpage.c | 3 ++-
 src/backend/access/nbtree/nbtxlog.c | 4 ++--
 src/include/access/nbtree.h         | 5 +++--
 3 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index c0502e55833..4aa7599351f 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.120 2010/02/26 02:00:34 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.121 2010/03/19 10:41:21 sriggs Exp $
  *
  *	NOTES
  *	   Postgres btree pages look like ordinary relation pages.	The opaque
@@ -1301,6 +1301,7 @@ _bt_pagedel(Relation rel, Buffer buf, BTStack stack)
 		xlrec.deadblk = target;
 		xlrec.leftblk = leftsib;
 		xlrec.rightblk = rightsib;
+		xlrec.btpo_xact = opaque->btpo.xact;
 
 		rdata[0].data = (char *) &xlrec;
 		rdata[0].len = SizeOfBtreeDeletePage;
diff --git a/src/backend/access/nbtree/nbtxlog.c b/src/backend/access/nbtree/nbtxlog.c
index 07416d599b5..782778cc7cd 100644
--- a/src/backend/access/nbtree/nbtxlog.c
+++ b/src/backend/access/nbtree/nbtxlog.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.62 2010/02/26 02:00:34 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.63 2010/03/19 10:41:22 sriggs Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -729,7 +729,7 @@ btree_xlog_delete_page(uint8 info, XLogRecPtr lsn, XLogRecord *record)
 
 	pageop->btpo_prev = leftsib;
 	pageop->btpo_next = rightsib;
-	pageop->btpo.xact = FrozenTransactionId;
+	pageop->btpo.xact = xlrec->btpo_xact;
 	pageop->btpo_flags = BTP_DELETED;
 	pageop->btpo_cycleid = 0;
 
diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h
index 8b7c33e61f1..eb96b2ad488 100644
--- a/src/include/access/nbtree.h
+++ b/src/include/access/nbtree.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.130 2010/02/26 02:01:21 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.131 2010/03/19 10:41:22 sriggs Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -375,7 +375,7 @@ typedef struct xl_btree_vacuum
  * identifies the tuple removed from the parent page (note that we remove
  * this tuple's downlink and the *following* tuple's key).	Note we do not
  * store any content for the deleted page --- it is just rewritten as empty
- * during recovery.
+ * during recovery, apart from resetting the btpo.xact.
  */
 typedef struct xl_btree_delete_page
 {
@@ -383,6 +383,7 @@ typedef struct xl_btree_delete_page
 	BlockNumber deadblk;		/* child block being deleted */
 	BlockNumber leftblk;		/* child block's left sibling, if any */
 	BlockNumber rightblk;		/* child block's right sibling */
+	TransactionId btpo_xact;	/* value of btpo.xact for use in recovery */
 	/* xl_btree_metadata FOLLOWS IF XLOG_BTREE_DELETE_PAGE_META */
 } xl_btree_delete_page;
 
-- 
GitLab