diff options
author | Peter Geoghegan <pg@bowt.ie> | 2019-08-12 15:21:32 -0700 |
---|---|---|
committer | Peter Geoghegan <pg@bowt.ie> | 2019-08-12 15:21:32 -0700 |
commit | 6754fe65a4c68c1e3b179080ab62c2f3ff6d877c (patch) | |
tree | b8295cc73a43fb965857e09729220ac259845526 | |
parent | 03c811a483b243952874d8e2b3f0c2e3793bc952 (diff) | |
download | postgresql-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.c | 45 |
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 |