mirror of
https://github.com/postgres/postgres.git
synced 2025-04-20 00:42:27 +03:00
Fix handling of non-upgraded B-tree metapages
857f9c36 bumps B-tree metapage version while upgrade is performed "on the fly" when needed. However, some asserts fired when old version metapage was cached to rel->rd_amcache. Despite new metadata fields are never used from rel->rd_amcache, that needs to be fixed. This patch introduces metadata upgrade during its caching, which fills unavailable fields with their default values. contrib/pageinspect is also patched to handle non-upgraded metapages in the same way. Author: Alexander Korotkov
This commit is contained in:
parent
01b88b4df5
commit
0a64b45152
@ -555,8 +555,21 @@ bt_metap(PG_FUNCTION_ARGS)
|
|||||||
values[j++] = psprintf("%d", metad->btm_level);
|
values[j++] = psprintf("%d", metad->btm_level);
|
||||||
values[j++] = psprintf("%d", metad->btm_fastroot);
|
values[j++] = psprintf("%d", metad->btm_fastroot);
|
||||||
values[j++] = psprintf("%d", metad->btm_fastlevel);
|
values[j++] = psprintf("%d", metad->btm_fastlevel);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get values of extended metadata if available, use default values
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
if (metad->btm_version == BTREE_VERSION)
|
||||||
|
{
|
||||||
values[j++] = psprintf("%u", metad->btm_oldest_btpo_xact);
|
values[j++] = psprintf("%u", metad->btm_oldest_btpo_xact);
|
||||||
values[j++] = psprintf("%lf", metad->btm_last_cleanup_num_heap_tuples);
|
values[j++] = psprintf("%lf", metad->btm_last_cleanup_num_heap_tuples);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
values[j++] = "0";
|
||||||
|
values[j++] = "-1";
|
||||||
|
}
|
||||||
|
|
||||||
tuple = BuildTupleFromCStrings(TupleDescGetAttInMetadata(tupleDesc),
|
tuple = BuildTupleFromCStrings(TupleDescGetAttInMetadata(tupleDesc),
|
||||||
values);
|
values);
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "storage/predicate.h"
|
#include "storage/predicate.h"
|
||||||
#include "utils/snapmgr.h"
|
#include "utils/snapmgr.h"
|
||||||
|
|
||||||
|
static void _bt_cachemetadata(Relation rel, BTMetaPageData *metad);
|
||||||
static bool _bt_mark_page_halfdead(Relation rel, Buffer buf, BTStack stack);
|
static bool _bt_mark_page_halfdead(Relation rel, Buffer buf, BTStack stack);
|
||||||
static bool _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf,
|
static bool _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf,
|
||||||
bool *rightsib_empty);
|
bool *rightsib_empty);
|
||||||
@ -105,6 +106,44 @@ _bt_upgrademetapage(Page page)
|
|||||||
((char *) metad + sizeof(BTMetaPageData)) - (char *) page;
|
((char *) metad + sizeof(BTMetaPageData)) - (char *) page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cache metadata from meta page to rel->rd_amcache.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
_bt_cachemetadata(Relation rel, BTMetaPageData *metad)
|
||||||
|
{
|
||||||
|
/* We assume rel->rd_amcache was already freed by caller */
|
||||||
|
Assert(rel->rd_amcache == NULL);
|
||||||
|
rel->rd_amcache = MemoryContextAlloc(rel->rd_indexcxt,
|
||||||
|
sizeof(BTMetaPageData));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Meta page should be of supported version (should be already checked by
|
||||||
|
* caller).
|
||||||
|
*/
|
||||||
|
Assert(metad->btm_version >= BTREE_MIN_VERSION &&
|
||||||
|
metad->btm_version <= BTREE_VERSION);
|
||||||
|
|
||||||
|
if (metad->btm_version == BTREE_VERSION)
|
||||||
|
{
|
||||||
|
/* Last version of meta-data, no need to upgrade */
|
||||||
|
memcpy(rel->rd_amcache, metad, sizeof(BTMetaPageData));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BTMetaPageData *cached_metad = (BTMetaPageData *) rel->rd_amcache;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Upgrade meta-data: copy available information from meta-page and
|
||||||
|
* fill new fields with default values.
|
||||||
|
*/
|
||||||
|
memcpy(rel->rd_amcache, metad, offsetof(BTMetaPageData, btm_oldest_btpo_xact));
|
||||||
|
cached_metad->btm_version = BTREE_VERSION;
|
||||||
|
cached_metad->btm_oldest_btpo_xact = InvalidTransactionId;
|
||||||
|
cached_metad->btm_last_cleanup_num_heap_tuples = -1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* _bt_update_meta_cleanup_info() -- Update cleanup-related information in
|
* _bt_update_meta_cleanup_info() -- Update cleanup-related information in
|
||||||
* the metapage.
|
* the metapage.
|
||||||
@ -403,9 +442,7 @@ _bt_getroot(Relation rel, int access)
|
|||||||
/*
|
/*
|
||||||
* Cache the metapage data for next time
|
* Cache the metapage data for next time
|
||||||
*/
|
*/
|
||||||
rel->rd_amcache = MemoryContextAlloc(rel->rd_indexcxt,
|
_bt_cachemetadata(rel, metad);
|
||||||
sizeof(BTMetaPageData));
|
|
||||||
memcpy(rel->rd_amcache, metad, sizeof(BTMetaPageData));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We are done with the metapage; arrange to release it via first
|
* We are done with the metapage; arrange to release it via first
|
||||||
@ -604,9 +641,7 @@ _bt_getrootheight(Relation rel)
|
|||||||
/*
|
/*
|
||||||
* Cache the metapage data for next time
|
* Cache the metapage data for next time
|
||||||
*/
|
*/
|
||||||
rel->rd_amcache = MemoryContextAlloc(rel->rd_indexcxt,
|
_bt_cachemetadata(rel, metad);
|
||||||
sizeof(BTMetaPageData));
|
|
||||||
memcpy(rel->rd_amcache, metad, sizeof(BTMetaPageData));
|
|
||||||
|
|
||||||
_bt_relbuf(rel, metabuf);
|
_bt_relbuf(rel, metabuf);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user