From 423a21396f1571b38424b9ef3280cdf529384f50 Mon Sep 17 00:00:00 2001 From: Peter Geoghegan Date: Mon, 15 Jul 2019 17:51:03 -0700 Subject: [PATCH] Fix nbtree metapage cache upgrade bug. It's not okay to update a cached copy of an indexes metapage metadata at a point where it isn't also being updated on disk. Discussion: https://postgr.es/m/CAH2-Wzmj6pz98qZ6+Ro-=tHvyBJ6q0yxHV8QLOr6O0mE20Nw9Q@mail.gmail.com --- src/backend/access/nbtree/nbtinsert.c | 3 ++- src/backend/access/nbtree/nbtpage.c | 20 ++++++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c index 602f8849d4..46a1167d65 100644 --- a/src/backend/access/nbtree/nbtinsert.c +++ b/src/backend/access/nbtree/nbtinsert.c @@ -1135,6 +1135,7 @@ _bt_insertonpg(Relation rel, if (BufferIsValid(metabuf)) { + /* _bt_upgrademetapage() should have been called */ Assert(metad->btm_version >= BTREE_NOVAC_VERSION); xlmeta.version = metad->btm_version; xlmeta.root = metad->btm_root; @@ -2160,7 +2161,7 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf) XLogRegisterBuffer(0, rootbuf, REGBUF_WILL_INIT); XLogRegisterBuffer(1, lbuf, REGBUF_STANDARD); XLogRegisterBuffer(2, metabuf, REGBUF_WILL_INIT | REGBUF_STANDARD); - + /* _bt_upgrademetapage() should have been called */ Assert(metad->btm_version >= BTREE_NOVAC_VERSION); md.version = metad->btm_version; md.root = rootblknum; diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c index 50455db9af..1da710ba90 100644 --- a/src/backend/access/nbtree/nbtpage.c +++ b/src/backend/access/nbtree/nbtpage.c @@ -135,14 +135,12 @@ _bt_cachemetadata(Relation rel, BTMetaPageData *input) else { /* - * Upgrade meta-data: copy available information from meta-page and - * fill new fields with default values. - * - * Note that we cannot upgrade to version 4+ without a REINDEX, since - * extensive on-disk changes are required. + * Copy available information from meta-page and fill new fields from + * later versions with default values defensively. The cached version + * number should not change, though. */ memcpy(cached_metad, input, offsetof(BTMetaPageData, btm_oldest_btpo_xact)); - cached_metad->btm_version = BTREE_NOVAC_VERSION; + cached_metad->btm_version = input->btm_version; cached_metad->btm_oldest_btpo_xact = InvalidTransactionId; cached_metad->btm_last_cleanup_num_heap_tuples = -1.0; } @@ -241,6 +239,7 @@ _bt_update_meta_cleanup_info(Relation rel, TransactionId oldestBtpoXact, XLogBeginInsert(); XLogRegisterBuffer(0, metabuf, REGBUF_WILL_INIT | REGBUF_STANDARD); + /* _bt_upgrademetapage() should have been called */ Assert(metad->btm_version >= BTREE_NOVAC_VERSION); md.version = metad->btm_version; md.root = metad->btm_root; @@ -439,6 +438,7 @@ _bt_getroot(Relation rel, int access) XLogRegisterBuffer(0, rootbuf, REGBUF_WILL_INIT); XLogRegisterBuffer(2, metabuf, REGBUF_WILL_INIT | REGBUF_STANDARD); + /* _bt_upgrademetapage() should have been called */ Assert(metad->btm_version >= BTREE_NOVAC_VERSION); md.version = metad->btm_version; md.root = rootblkno; @@ -660,7 +660,7 @@ _bt_getrootheight(Relation rel) _bt_cachemetadata(rel, metad); /* We shouldn't have cached it if any of these fail */ Assert(metad->btm_magic == BTREE_MAGIC); - Assert(metad->btm_version >= BTREE_NOVAC_VERSION); + Assert(metad->btm_version >= BTREE_MIN_VERSION); Assert(metad->btm_fastroot != P_NONE); _bt_relbuf(rel, metabuf); } @@ -711,7 +711,7 @@ _bt_heapkeyspace(Relation rel) _bt_cachemetadata(rel, metad); /* We shouldn't have cached it if any of these fail */ Assert(metad->btm_magic == BTREE_MAGIC); - Assert(metad->btm_version >= BTREE_NOVAC_VERSION); + Assert(metad->btm_version >= BTREE_MIN_VERSION); Assert(metad->btm_fastroot != P_NONE); _bt_relbuf(rel, metabuf); } @@ -2094,6 +2094,10 @@ _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf, bool *rightsib_empty) { XLogRegisterBuffer(4, metabuf, REGBUF_WILL_INIT | REGBUF_STANDARD); + /* + * _bt_upgrademetapage() should have been called when root needs + * to be updated + */ Assert(metad->btm_version >= BTREE_NOVAC_VERSION); xlmeta.version = metad->btm_version; xlmeta.root = metad->btm_root; -- 2.17.1