Newsletter
TechAnV Blog
Get updates on security engineering, Rust, eBPF, and DevSecOps. No spam, unsubscribe anytime.
Check your inbox and click the confirmation link to complete your subscription.
Compiling and running sqlite3-rsync#
Today I heard about the sqlite3-rsync command, currently available in a branch in the SQLite code repository. It provides a mechanism for efficiently creating or updating a copy of a SQLite database that is running in WAL mode, either locally or via SSH to another server.
Update: Thanks to gary_0 on Hacker News here’s a MUCH simpler recipe:
1git clone https://github.com/sqlite/sqlite.git2cd sqlite3./configure4make sqlite3-rsyncSo it looks like the sqlite-rsync command is no longer limited to a branch.
How I compiled it without using make sqlite3-rsync#
After some poking around (and some hints from Claude) I found a recipe for compiling and running it that seems to work:
1cd /tmp2git clone https://github.com/sqlite/sqlite.git3cd sqlite4git checkout sqlite3-rsync5./configure6make sqlite3.c7cd tool8gcc -o sqlite3-rsync sqlite3-rsync.c ../sqlite3.c -DSQLITE_ENABLE_DBPAGE_VTAB9./sqlite3-rsync --helpHere I’m cloning from the GitHub mirror of the SQLite Fossil repo, purely to save myself from learning how to use Fossil.
The first step is to run ./configure and then make sqlite3.c in the root directory. This creates the SQLite amalgamation file - a single C file containing the full implementation of SQLite, which I can then use as part of compiling the sqlite3-rsync tool.
It took me quite a few iterations to get to this recipe for compiling the tool itself:
1gcc -o sqlite3-rsync sqlite3-rsync.c ../sqlite3.c -DSQLITE_ENABLE_DBPAGE_VTABThe -DSQLITE_ENABLE_DBPAGE_VTAB flag is necessary to enable the dbpage virtual table, which is used by the sqlite3-rsync tool. Without that I got this error when trying to run it:
ERROR: unable to prepare SQL [SELECT hash(data) FROM sqlite_dbpage WHERE pgno<=min(1,7338) ORDER BY pgno]: no such table: sqlite_dbpage
Trying out sqlite-rsync#
Having compiled the utility I tested it out like this:
1curl https://datasette.io/content.db -o /tmp/content.db2# Enable WAL mode3sqlite3 /tmp/content.db "PRAGMA journal_mode=WAL"4# And run the copy5./sqlite3-rsync /tmp/content.db /tmp/content-copy.dbThen I made a change to /tmp/content.db:
1sqlite3 /tmp/content.db 'create table test (id integer primary key)'Confirmed it was not present in /tmp/content-copy.db:
1sqlite3 /tmp/content-copy.db '.tables'And ran this command to sync them up again:
1./sqlite3-rsync /tmp/content.db /tmp/content-copy.dbWhich resulted in that new table being created in the copy:
1sqlite3 /tmp/content-copy.db '.tables' | grep testI haven’t yet tried running the command over SSH: you first need to compile and deploy the sqlite3-rsync binary to the remote server and drop it somewhere on the path (the documentation suggests /usr/local/bin).
Having done that this should work:
1sqlite3-rsync user@host:/path/to/remote.db /path/to/local-copy.db