0003-Defend-against-heapallindexed-using-transaction-snap.patch
text/x-patch
Filename: 0003-Defend-against-heapallindexed-using-transaction-snap.patch
Type: text/x-patch
Part: 0
Patch
Format: format-patch
Series: patch 0003
Subject: Defend against heapallindexed using transaction snapshot.
| File | + | − |
|---|---|---|
| contrib/amcheck/verify_nbtree.c | 25 | 0 |
From 080e3b512a0ad80147cd8d6aaba02e9df5b92daf Mon Sep 17 00:00:00 2001
From: Peter Geoghegan <pg@bowt.ie>
Date: Tue, 27 Mar 2018 13:33:33 -0700
Subject: [PATCH 3/3] Defend against heapallindexed using transaction snapshot.
---
contrib/amcheck/verify_nbtree.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/contrib/amcheck/verify_nbtree.c b/contrib/amcheck/verify_nbtree.c
index c3380895a9..105945ee3b 100644
--- a/contrib/amcheck/verify_nbtree.c
+++ b/contrib/amcheck/verify_nbtree.c
@@ -23,8 +23,10 @@
*/
#include "postgres.h"
+#include "access/htup_details.h"
#include "access/nbtree.h"
#include "access/transam.h"
+#include "access/xact.h"
#include "catalog/index.h"
#include "catalog/pg_am.h"
#include "commands/tablecmds.h"
@@ -360,7 +362,30 @@ bt_check_every_level(Relation rel, Relation heaprel, bool readonly,
* IndexBuildHeapScan().
*/
if (!state->readonly)
+ {
snapshot = RegisterSnapshot(GetTransactionSnapshot());
+
+ /*
+ * GetTransactionSnapshot() always acquires a new MVCC snapshot in
+ * READ COMMITTED mode. A new snapshot is guaranteed to have all
+ * the entries it requires in the index.
+ *
+ * We must defend against the possibility that an old xact snapshot
+ * was returned at higher isolation levels when that snapshot is
+ * not safe for index scans of the target index. This is possible
+ * when the snapshot sees tuples that are before the index's
+ * indcheckxmin horizon. Throwing an error here should be very
+ * rare. It doesn't seem worth using a secondary snapshot to avoid
+ * this.
+ */
+ if (IsolationUsesXactSnapshot() && rel->rd_index->indcheckxmin &&
+ !TransactionIdPrecedes(HeapTupleHeaderGetXmin(rel->rd_indextuple->t_data),
+ snapshot->xmin))
+ ereport(ERROR,
+ (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
+ errmsg("index \"%s\" cannot be verified using transaction snapshot",
+ RelationGetRelationName(rel))));
+ }
}
/* Create context for page */
--
2.14.1