Synapse currently has the concept of a database "schema version", which is used to forestall problems where a database update is performed, but the deployment is then rolled back to an earlier version, causing incompatibility.
This is implemented via the synapse.storage.prepare_database.SCHEMA_VERSION
constant and the schema_version.version
database column.
The problem with this approach is that it makes it impossible to roll Synapse
back to an earlier version. In practice, we often take a "rolling" approach to
schema changes. For example, consider the situation where a database table
(say, old_table
) becomes redundant; we might do the following:
old_table
, but keep writing
to it in case of rollback to version N.old_table
, but don't yet
remove the table in case of rollback to version N+1.old_table
completely.The precise details vary, but such a pattern of gradually evolving database code in a way that maintains compatibility with one or two earlier versions is not uncommon.
Ideally, we would complain about attempts to roll back from N+2 to N, whilst
allowing roll-back from N+1 to N or N+2 to N+1; however the schema_version
implementation makes that impossible.
schema_version.version
to indicate the oldest
SCHEMA_VERSION
that the database is compatible with.schema_version.version
is greater
than synapse.storage.prepare_database.SCHEMA_VERSION
.schema_version.version
is no longer set to prepare_database.SCHEMA_VERSION
(we probably need a different constant for it).In the above example:
Synapse version N+1 would have prepare_database.SCHEMA_VERSION=N+1
,
(and would add its delta files to delta/<N+1>
) to reflect that it uses
the database differently to version N, but would set
schema_version.version=N
, since the database will still be compatible
with Synapse version N.
Likewise, Synapse version N+2 would set prepare_database.SCHEMA_VERSION=N+2
,
and must set schema_version.version=N+1
, to denote that we have broken
compatibility with version N.