Skip to content

Use WAL mode for SQLite cache databases#13800

Merged
edolstra merged 3 commits intomasterfrom
concurrent-eval-cache
Aug 21, 2025
Merged

Use WAL mode for SQLite cache databases#13800
edolstra merged 3 commits intomasterfrom
concurrent-eval-cache

Conversation

@edolstra
Copy link
Member

Motivation

With "truncate" mode, if we try to write to the database while another process has an active write transaction, we'll block until the other transaction finishes. This is a problem for the evaluation cache in particular, since it uses long-running transactions. I.e. other Nix commands operating on the same flake could be blocked for an unbounded amount of time.

WAL mode does not have this issue: it just returns "busy" right away, so Nix will print

error (ignored): SQLite database '/home/eelco/.cache/nix/eval-cache-v5/...' is busy

and stop trying to write to the evaluation cache. (This was the intended/original behaviour, see AttrDb::doSQLite().)

A quick benchmark (running nix search github:NixOS/nixpkgs/bf8462aeba50cc753971480f613fbae0747cffc0?narHash=sha256-bPyv7hsbtuxyL6LLKtOYL6QsmPeFWP839BZQMd3RoUg%3D 20 times) did not show a significant performance difference:

user CPU time:      median =     16.2447  mean =     16.2527  stddev =      0.1150  min =     16.0922  max =     16.4433  [not rejected, p=0.90746, Δ=-0.00431±0.11047]
elapsed time:       median =     20.2731  mean =     20.2867  stddev =      1.1840  min =     18.8877  max =     21.6970  [not rejected, p=0.80504, Δ=-0.10797±1.30295]

This PR also updates the versions of the SQLite caches. This avoids problems with older versions of Nix that don't put the caches in WAL mode. That's generally not a problem, until you do something like

nix build --print-out-paths ... | cachix

which deadlocks because cachix tries to switch the caches to truncate mode, which requires exclusive access. But the first process cannot make progress because the cachix process isn't reading from the pipe.

Based on DeterminateSystems#150, DeterminateSystems#167.

Context


Add 👍 to pull requests you find important.

The Nix maintainer team uses a GitHub project board to schedule and track reviews.

With "truncate" mode, if we try to write to the database while another
process has an active write transaction, we'll block until the other
transaction finishes. This is a problem for the evaluation cache in
particular, since it uses long-running transactions.

WAL mode does not have this issue: it just returns "busy" right away,
so Nix will print

  error (ignored): SQLite database '/home/eelco/.cache/nix/eval-cache-v5/...' is busy

and stop trying to write to the evaluation cache. (This was the
intended/original behaviour, see AttrDb::doSQLite().)
This avoids problems with older versions of Nix that don't put the
caches in WAL mode. That's generally not a problem, until you do something like

  nix build --print-out-paths ... | cachix

which deadlocks because cachix tries to switch the caches to truncate
mode, which requires exclusive access. But the first process cannot
make progress because the cachix process isn't reading from the pipe.
@edolstra edolstra requested a review from Ericson2314 as a code owner August 20, 2025 18:51
@github-actions github-actions bot added store Issues and pull requests concerning the Nix store fetching Networking with the outside (non-Nix) world, input locking labels Aug 20, 2025
Copy link
Member

@Ericson2314 Ericson2314 left a comment

Choose a reason for hiding this comment

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

I am not really the one to judge here, as I don't have much hands-on experience with the eval cache, but we use "wal" elsewhere, and the commit messages / PR description makes sense.

@edolstra edolstra merged commit 615b10c into master Aug 21, 2025
29 checks passed
@edolstra edolstra deleted the concurrent-eval-cache branch August 21, 2025 09:42
@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/nix-2-31-0-released/68465/1

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

Labels

fetching Networking with the outside (non-Nix) world, input locking store Issues and pull requests concerning the Nix store

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants