Handle old versioned columnar metapage after binary upgrade (#4956)

* Make VACUUM hint for upgrade scenario actually work

* Suggest using VACUUM if metapage doesn't exist

Plus, suggest upgrading sql version as another option.

* Always force read metapage block

* Fix two typos
pull/5052/head
Onur Tirtir 2021-05-07 17:18:21 +03:00
parent 2e419ea177
commit 2552aee404
3 changed files with 32 additions and 7 deletions

View File

@ -87,6 +87,10 @@ typedef struct PhysicalAddr
#define COLUMNAR_FIRST_STRIPE_ID 1 #define COLUMNAR_FIRST_STRIPE_ID 1
#define OLD_METAPAGE_VERSION_HINT "Use \"VACUUM\" to upgrade the columnar table format " \
"version or run \"ALTER EXTENSION citus UPDATE\"."
/* /*
* Map logical offsets to a physical page and offset where the data is kept. * Map logical offsets to a physical page and offset where the data is kept.
*/ */
@ -325,7 +329,7 @@ ColumnarStorageGetReservedOffset(Relation rel, bool force)
/* /*
* ColumnarMetapageNeedsUpgrade - return true if metapage exists and is not * ColumnarStorageIsCurrent - return true if metapage exists and is not
* the current version. * the current version.
*/ */
bool bool
@ -610,13 +614,27 @@ ColumnarMetapageRead(Relation rel, bool force)
BlockNumber nblocks = smgrnblocks(rel->rd_smgr, MAIN_FORKNUM); BlockNumber nblocks = smgrnblocks(rel->rd_smgr, MAIN_FORKNUM);
if (nblocks == 0) if (nblocks == 0)
{ {
elog(ERROR, "columnar metapage for relation \"%s\" does not exist", /*
RelationGetRelationName(rel)); * We only expect this to happen during binary ugrades. This is because,
* in current version of columnar, we immediately create the metapage
* for columnar tables, i.e right after creating the table.
* However in older versions, we were creating metapages lazily, i.e
* when ingesting data to columnar table.
*/
ereport(ERROR, (errmsg("columnar metapage for relation \"%s\" does not exist",
RelationGetRelationName(rel)),
errhint(OLD_METAPAGE_VERSION_HINT)));
} }
/*
* Regardless of "force" parameter, always force read metapage block.
* We will check metapage version in ColumnarMetapageCheckVersion
* depending on "force".
*/
bool forceReadBlock = true;
ColumnarMetapage metapage; ColumnarMetapage metapage;
ReadFromBlock(rel, COLUMNAR_METAPAGE_BLOCKNO, SizeOfPageHeaderData, ReadFromBlock(rel, COLUMNAR_METAPAGE_BLOCKNO, SizeOfPageHeaderData,
(char *) &metapage, sizeof(ColumnarMetapage), force); (char *) &metapage, sizeof(ColumnarMetapage), forceReadBlock);
if (!force) if (!force)
{ {
@ -786,7 +804,6 @@ ColumnarMetapageCheckVersion(Relation rel, ColumnarMetapage *metapage)
COLUMNAR_VERSION_MAJOR, COLUMNAR_VERSION_MINOR, COLUMNAR_VERSION_MAJOR, COLUMNAR_VERSION_MINOR,
RelationGetRelationName(rel), RelationGetRelationName(rel),
metapage->versionMajor, metapage->versionMinor), metapage->versionMajor, metapage->versionMinor),
errhint( errhint(OLD_METAPAGE_VERSION_HINT)));
"Use VACUUM to upgrade the columnar table format version.")));
} }
} }

View File

@ -696,6 +696,14 @@ static void
columnar_vacuum_rel(Relation rel, VacuumParams *params, columnar_vacuum_rel(Relation rel, VacuumParams *params,
BufferAccessStrategy bstrategy) BufferAccessStrategy bstrategy)
{ {
/*
* If metapage version of relation is older, then we hint users to VACUUM
* the relation in ColumnarMetapageCheckVersion. So if needed, upgrade
* the metapage before doing anything.
*/
bool isUpgrade = true;
ColumnarStorageUpdateIfNeeded(rel, isUpgrade);
int elevel = (params->options & VACOPT_VERBOSE) ? INFO : DEBUG2; int elevel = (params->options & VACOPT_VERBOSE) ? INFO : DEBUG2;
/* this should have been resolved by vacuum.c until now */ /* this should have been resolved by vacuum.c until now */

View File

@ -12,7 +12,7 @@ REFERENCES columnar.stripe(storage_id, stripe_num) ON DELETE CASCADE;
-- define columnar_ensure_objects_exist again -- define columnar_ensure_objects_exist again
#include "../udfs/columnar_ensure_objects_exist/10.0-1.sql" #include "../udfs/columnar_ensure_objects_exist/10.0-1.sql"
-- upgrade storage for all columnar relations -- downgrade storage for all columnar relations
SELECT citus_internal.downgrade_columnar_storage(c.oid) FROM pg_class c, pg_am a SELECT citus_internal.downgrade_columnar_storage(c.oid) FROM pg_class c, pg_am a
WHERE c.relam = a.oid AND amname = 'columnar'; WHERE c.relam = a.oid AND amname = 'columnar';