Quidest?

Gotchas with SQLite in Production

· Lorenzo Drumond

SQLite is a database library that allows to store databases in files. It is higlhy scalable and keeps the application stack simple.

There are few gotchas:

Configuration

It is not configured for multi-threaded access OOTB

PRAGMA foreign_keys = ON;
PRAGMA journal_mode=WAL;
PRAGMA synchronous=NORMAL;
PRAGMA mmap_size = 134217728;
PRAGMA journal_size_limit = 27103364;
PRAGMA cache_size=2000;

No connections over the network

Single file design makes it more difficutl to connect to the database from another machine. This makes it hard to guarantee availability of the database.

Network and ephemeral file systems

To solve above problem you could put the SQLite database on a network file system, but these don’t have locks and you risk to get a corrupted database.

Concurrency

SQLite limits writing to only one thread at a time, and the writing is per database.

To make this faster with SQLite, you can split your tables across multiple databases. This way, each database can write to its set of tables in parallel. Before going down this road, consider using MySQL or Postgres instead, as they might make your application code simpler.

Transactions

SQLite implements serializable transactions by using a write lock on the whole database for the duration of the transaction. This means that if you have a long-running transaction, you are blocking all other transactions and write operations for the duration of the transaction.

When working with transactions you should always use BEGIN IMMEDIATE instead of a regular BEGIN. The reason for this is that a read transaction cannot be upgraded to a write transaction, so you’ll be seeing database is locked errors not retrying until the BUSY_TIMEOUT runs out.

Backups

You might be tempted to copy/paste the SQLite file to create a backup, but this is a bad idea as it can corrupt the backup file. Instead, you should always use the VACUUM INTO command to create a full backup.

Migrations

SQLite has limited support for the ALTER statement, which relational schema migrations rely upon. Only adding and dropping columns and renaming tables are supported. This can make your database migrations more complicated.

References