From 080e3b512a0ad80147cd8d6aaba02e9df5b92daf Mon Sep 17 00:00:00 2001 From: Peter Geoghegan 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