Skip to content

fix(microvm-run): avoid db.sqlite backup restart loop under concurrent writes#11

Merged
systemstart merged 1 commit into
systemstart:mainfrom
devinrsmith:improve-sqlite3-backup
Jul 6, 2026
Merged

fix(microvm-run): avoid db.sqlite backup restart loop under concurrent writes#11
systemstart merged 1 commit into
systemstart:mainfrom
devinrsmith:improve-sqlite3-backup

Conversation

@devinrsmith

@devinrsmith devinrsmith commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

The nix store DB snapshot taken before VM boot used a plain .backup command, which the SQLite docs specify will restart from page 1 whenever the source database is modified by another connection mid-copy. On an actively used host, nix-daemon writes to db.sqlite frequently enough (builds, substitutions, GC, etc.) that the backup could be restarted continuously, observed as the sqlite3 process pegging a CPU core indefinitely — the bottleneck was repeated re-copying, not disk throughput.

Fix by opening an explicit read transaction on the same connection before running .backup. This pins a consistent snapshot up front, so external commits during the backup no longer invalidate already- copied pages and trigger a restart. Also add a 30s busy-timeout as a defensive measure in case another process holds a competing lock at the moment the transaction starts.

Ref: https://sqlite.org/forum/info/cca839708d74a20014f7188b86a19b267602d497bfa90ec1d1e79111a5b24adb

Summary by CodeRabbit

  • Bug Fixes
    • Improved VM startup reliability when copying the host Nix store database.
    • Reduced backup failures by taking a consistent snapshot before the copy begins.
    • Added a longer wait period and a quick consistency check to help prevent intermittent restore issues.

…t writes

The nix store DB snapshot taken before VM boot used a plain
`.backup` command, which the SQLite docs specify will restart from
page 1 whenever the source database is modified by another
connection mid-copy. On an actively used host, nix-daemon writes to
db.sqlite frequently enough (builds, substitutions, GC, etc.) that
the backup could be restarted continuously, observed as the sqlite3
process pegging a CPU core indefinitely — the bottleneck was
repeated re-copying, not disk throughput.

Fix by opening an explicit read transaction on the same connection
before running .backup. This pins a consistent snapshot up front, so
external commits during the backup no longer invalidate already-
copied pages and trigger a restart. Also add a 30s busy-timeout as a
defensive measure in case another process holds a competing lock at
the moment the transaction starts.

Ref: https://sqlite.org/forum/info/cca839708d74a20014f7188b86a19b267602d497bfa90ec1d1e79111a5b24adb

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 68d259af-fcf0-47f1-b24e-81e2a826e639

📥 Commits

Reviewing files that changed from the base of the PR and between 9caa9b4 and 1bb4576.

📒 Files selected for processing (1)
  • flake.nix

📝 Walkthrough

Walkthrough

Modifies flake.nix's VM runner script to wrap the SQLite Nix store database backup in an explicit read transaction with a timeout and consistency check, replacing the previous single-step .backup invocation, with updated explanatory comments.

Changes

SQLite Backup Mitigation

Layer / File(s) Summary
Transaction-pinned backup sequence
flake.nix
Comment updated to explain that pinning a read transaction prevents .backup restarts during concurrent writes; backup command now sets .timeout 30000, wraps .backup in BEGIN;/COMMIT;, and runs SELECT count(*) FROM sqlite_master; beforehand, with the destination path quoted.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main fix: preventing db.sqlite backup restart loops in microvm-run under concurrent writes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@systemstart systemstart left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for contributing.

@systemstart systemstart merged commit 14c119e into systemstart:main Jul 6, 2026
3 checks passed
@systemstart

Copy link
Copy Markdown
Owner

Added in v0.10.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants