aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Geoghegan <pg@bowt.ie>2019-08-12 15:21:32 -0700
committerPeter Geoghegan <pg@bowt.ie>2019-08-12 15:21:32 -0700
commit6754fe65a4c68c1e3b179080ab62c2f3ff6d877c (patch)
treeb8295cc73a43fb965857e09729220ac259845526
parent03c811a483b243952874d8e2b3f0c2e3793bc952 (diff)
downloadpostgresql-6754fe65a4c68c1e3b179080ab62c2f3ff6d877c.tar.gz
postgresql-6754fe65a4c68c1e3b179080ab62c2f3ff6d877c.zip
amcheck: Skip unlogged relations during recovery.
contrib/amcheck failed to consider the possibility that unlogged relations will not have any main relation fork files when running in hot standby mode. This led to low-level "can't happen" errors that complain about the absence of a relfilenode file. To fix, simply skip verification of unlogged index relations during recovery. In passing, add a direct check for the presence of a main fork just before verification proper begins, so that we cleanly verify the presence of the main relation fork file. Author: Andrey Borodin, Peter Geoghegan Reported-By: Andrey Borodin Diagnosed-By: Andrey Borodin Discussion: https://postgr.es/m/DA9B33AC-53CB-4643-96D4-7A0BBC037FA1@yandex-team.ru Backpatch: 10-, where amcheck was introduced.
-rw-r--r--contrib/amcheck/verify_nbtree.c45
1 files changed, 40 insertions, 5 deletions
diff --git a/contrib/amcheck/verify_nbtree.c b/contrib/amcheck/verify_nbtree.c
index 55a3a4bbe0c..05e7d678ed4 100644
--- a/contrib/amcheck/verify_nbtree.c
+++ b/contrib/amcheck/verify_nbtree.c
@@ -35,6 +35,7 @@
#include "lib/bloomfilter.h"
#include "miscadmin.h"
#include "storage/lmgr.h"
+#include "storage/smgr.h"
#include "utils/memutils.h"
#include "utils/snapmgr.h"
@@ -128,6 +129,7 @@ PG_FUNCTION_INFO_V1(bt_index_parent_check);
static void bt_index_check_internal(Oid indrelid, bool parentcheck,
bool heapallindexed, bool rootdescend);
static inline void btree_index_checkable(Relation rel);
+static inline bool btree_index_mainfork_expected(Relation rel);
static void bt_check_every_level(Relation rel, Relation heaprel,
bool heapkeyspace, bool readonly, bool heapallindexed,
bool rootdescend);
@@ -225,7 +227,6 @@ bt_index_check_internal(Oid indrelid, bool parentcheck, bool heapallindexed,
Oid heapid;
Relation indrel;
Relation heaprel;
- bool heapkeyspace;
LOCKMODE lockmode;
if (parentcheck)
@@ -275,10 +276,22 @@ bt_index_check_internal(Oid indrelid, bool parentcheck, bool heapallindexed,
/* Relation suitable for checking as B-Tree? */
btree_index_checkable(indrel);
- /* Check index, possibly against table it is an index on */
- heapkeyspace = _bt_heapkeyspace(indrel);
- bt_check_every_level(indrel, heaprel, heapkeyspace, parentcheck,
- heapallindexed, rootdescend);
+ if (btree_index_mainfork_expected(indrel))
+ {
+ bool heapkeyspace;
+
+ RelationOpenSmgr(indrel);
+ if (!smgrexists(indrel->rd_smgr, MAIN_FORKNUM))
+ ereport(ERROR,
+ (errcode(ERRCODE_INDEX_CORRUPTED),
+ errmsg("index \"%s\" lacks a main relation fork",
+ RelationGetRelationName(indrel))));
+
+ /* Check index, possibly against table it is an index on */
+ heapkeyspace = _bt_heapkeyspace(indrel);
+ bt_check_every_level(indrel, heaprel, heapkeyspace, parentcheck,
+ heapallindexed, rootdescend);
+ }
/*
* Release locks early. That's ok here because nothing in the called
@@ -325,6 +338,28 @@ btree_index_checkable(Relation rel)
}
/*
+ * Check if B-Tree index relation should have a file for its main relation
+ * fork. Verification uses this to skip unlogged indexes when in hot standby
+ * mode, where there is simply nothing to verify.
+ *
+ * NB: Caller should call btree_index_checkable() before calling here.
+ */
+static inline bool
+btree_index_mainfork_expected(Relation rel)
+{
+ if (rel->rd_rel->relpersistence != RELPERSISTENCE_UNLOGGED ||
+ !RecoveryInProgress())
+ return true;
+
+ ereport(NOTICE,
+ (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
+ errmsg("cannot verify unlogged index \"%s\" during recovery, skipping",
+ RelationGetRelationName(rel))));
+
+ return false;
+}
+
+/*
* Main entry point for B-Tree SQL-callable functions. Walks the B-Tree in
* logical order, verifying invariants as it goes. Optionally, verification
* checks if the heap relation contains any tuples that are not represented in