Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Refuse to start if sqlite is older than 3.11.0 #6675

Merged
merged 5 commits into from
Jan 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ sudo yum install libtiff-devel libjpeg-devel libzip-devel freetype-devel \
sudo yum groupinstall "Development Tools"
```

Note that Synapse does not support versions of SQLite before 3.11, and CentOS 7
uses SQLite 3.7. You may be able to work around this by installing a more
recent SQLite version, but it is recommended that you instead use a Postgres
database: see [docs/postgres.md](docs/postgres.md).

#### macOS

Installing prerequisites on macOS:
Expand Down
1 change: 1 addition & 0 deletions changelog.d/6675.removal
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Synapse no longer supports versions of SQLite before 3.11, and will refuse to start when configured to use an older version. Administrators are recommended to migrate their database to Postgres (see instructions [here](docs/postgres.md)).
39 changes: 18 additions & 21 deletions scripts/synapse_port_db
Original file line number Diff line number Diff line change
Expand Up @@ -447,37 +447,32 @@ class Porter(object):
else:
return

def setup_db(self, db_config: DatabaseConnectionConfig, engine):
db_conn = make_conn(db_config, engine)
prepare_database(db_conn, engine, config=None)

db_conn.commit()

return db_conn

@defer.inlineCallbacks
def build_db_store(self, db_config: DatabaseConnectionConfig):
def build_db_store(
self, db_config: DatabaseConnectionConfig, allow_outdated_version: bool = False,
):
"""Builds and returns a database store using the provided configuration.

Args:
config: The database configuration
db_config: The database configuration
allow_outdated_version: True to suppress errors about the database server
version being too old to run a complete synapse

Returns:
The built Store object.
"""
self.progress.set_state("Preparing %s" % db_config.config["name"])

engine = create_engine(db_config.config)
conn = self.setup_db(db_config, engine)

hs = MockHomeserver(self.hs_config)

store = Store(Database(hs, db_config, engine), conn, hs)

yield store.db.runInteraction(
"%s_engine.check_database" % db_config.config["name"],
engine.check_database,
)
with make_conn(db_config, engine) as db_conn:
engine.check_database(
db_conn, allow_outdated_version=allow_outdated_version
)
prepare_database(db_conn, engine, config=None)
store = Store(Database(hs, db_config, engine), db_conn, hs)
db_conn.commit()

return store

Expand All @@ -502,8 +497,10 @@ class Porter(object):
@defer.inlineCallbacks
def run(self):
try:
self.sqlite_store = yield self.build_db_store(
DatabaseConnectionConfig("master-sqlite", self.sqlite_config)
# we allow people to port away from outdated versions of sqlite.
self.sqlite_store = self.build_db_store(
DatabaseConnectionConfig("master-sqlite", self.sqlite_config),
allow_outdated_version=True,
)

# Check if all background updates are done, abort if not.
Expand All @@ -518,7 +515,7 @@ class Porter(object):
)
defer.returnValue(None)

self.postgres_store = yield self.build_db_store(
self.postgres_store = self.build_db_store(
self.hs_config.get_single_database()
)

Expand Down
2 changes: 1 addition & 1 deletion synapse/storage/data_stores/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def __init__(self, main_store_class, hs):
with make_conn(database_config, engine) as db_conn:
logger.info("Preparing database %r...", db_name)

engine.check_database(db_conn.cursor())
engine.check_database(db_conn)
prepare_database(
db_conn, engine, hs.config, data_stores=database_config.data_stores,
)
Expand Down
34 changes: 17 additions & 17 deletions synapse/storage/engines/postgres.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,30 +32,30 @@ def _disable_bytes_adapter(_):
self.synchronous_commit = database_config.get("synchronous_commit", True)
self._version = None # unknown as yet

def check_database(self, txn):
txn.execute("SHOW SERVER_ENCODING")
rows = txn.fetchall()
if rows and rows[0][0] != "UTF8":
raise IncorrectDatabaseSetup(
"Database has incorrect encoding: '%s' instead of 'UTF8'\n"
"See docs/postgres.rst for more information." % (rows[0][0],)
)

def convert_param_style(self, sql):
return sql.replace("?", "%s")

def on_new_connection(self, db_conn):

def check_database(self, db_conn, allow_outdated_version: bool = False):
# Get the version of PostgreSQL that we're using. As per the psycopg2
# docs: The number is formed by converting the major, minor, and
# revision numbers into two-decimal-digit numbers and appending them
# together. For example, version 8.1.5 will be returned as 80105
self._version = db_conn.server_version

# Are we on a supported PostgreSQL version?
if self._version < 90500:
if not allow_outdated_version and self._version < 90500:
raise RuntimeError("Synapse requires PostgreSQL 9.5+ or above.")

with db_conn.cursor() as txn:
txn.execute("SHOW SERVER_ENCODING")
rows = txn.fetchall()
if rows and rows[0][0] != "UTF8":
raise IncorrectDatabaseSetup(
"Database has incorrect encoding: '%s' instead of 'UTF8'\n"
"See docs/postgres.rst for more information." % (rows[0][0],)
)

def convert_param_style(self, sql):
return sql.replace("?", "%s")

def on_new_connection(self, db_conn):
db_conn.set_isolation_level(
self.module.extensions.ISOLATION_LEVEL_REPEATABLE_READ
)
Expand Down Expand Up @@ -119,8 +119,8 @@ def server_version(self):
Returns:
string
"""
# note that this is a bit of a hack because it relies on on_new_connection
# having been called at least once. Still, that should be a safe bet here.
# note that this is a bit of a hack because it relies on check_database
# having been called. Still, that should be a safe bet here.
numver = self._version
assert numver is not None

Expand Down
7 changes: 5 additions & 2 deletions synapse/storage/engines/sqlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,11 @@ def supports_using_any_list(self):
"""
return False

def check_database(self, txn):
pass
def check_database(self, db_conn, allow_outdated_version: bool = False):
if not allow_outdated_version:
version = self.module.sqlite_version_info
if version < (3, 11, 0):
raise RuntimeError("Synapse requires sqlite 3.11 or above.")

def convert_param_style(self, sql):
return sql
Expand Down