Skip to content

Support fine-grained database schema migrations#11668

Merged
Ericson2314 merged 1 commit intoNixOS:masterfrom
DeterminateSystems:schema-migrations
Nov 20, 2024
Merged

Support fine-grained database schema migrations#11668
Ericson2314 merged 1 commit intoNixOS:masterfrom
DeterminateSystems:schema-migrations

Conversation

@edolstra
Copy link
Member

Motivation

Backward-compatible schema changes (e.g. those that add tables or nullable columns) now no longer need a change to the global schema file (/nix/var/nix/db/schema). Thus, old Nix versions can continue to access the database.

This is especially useful for schema changes required by experimental features. In particular, it replaces the ad-hoc handling of the schema changes for CA derivations (i.e. the file /nix/var/nix/db/ca-schema).

Schema versions 8 and 10 could have been handled by this mechanism in a backward-compatible way as well.

Context

Priorities and Process

Add 👍 to pull requests you find important.

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

@edolstra edolstra requested a review from Ericson2314 as a code owner October 10, 2024 15:00
@github-actions github-actions bot added the store Issues and pull requests concerning the Nix store label Oct 10, 2024
@Mic92
Copy link
Member

Mic92 commented Oct 15, 2024

Does this also help with the deadlock that are seeing when enabling ca derivations? Currently it requires a reboot of the machine because existing running nix processes will not allow the schema migration from happening as they hold the global lock file.

@edolstra
Copy link
Member Author

@Mic92 It should help with the deadlock since it doesn't hold the global lock anymore while doing SQLite schema migrations. (Maybe it should, but AFAIK SQLite doesn't need it.)

@Mic92
Copy link
Member

Mic92 commented Oct 16, 2024

Great that's my main road block to deploy this by default on a larger amount of machines

@nixos-discourse
Copy link

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

https://discourse.nixos.org/t/2024-10-16-nix-team-meeting-minutes-187/54835/1

@edolstra edolstra force-pushed the schema-migrations branch 2 times, most recently from 5e27a7c to 517e5da Compare October 25, 2024 12:55
Backward-compatible schema changes (e.g. those that add tables or
nullable columns) now no longer need a change to the global schema
file (/nix/var/nix/db/schema). Thus, old Nix versions can continue to
access the database.

This is especially useful for schema changes required by experimental
features. In particular, it replaces the ad-hoc handling of the schema
changes for CA derivations (i.e. the file /nix/var/nix/db/ca-schema).

Schema versions 8 and 10 could have been handled by this mechanism in
a backward-compatible way as well.
Copy link
Member

@bryanhonof bryanhonof left a comment

Choose a reason for hiding this comment

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

To me, this looks good. Haven't tested it out though, also not sure how one might test this.

@Mic92
Copy link
Member

Mic92 commented Nov 6, 2024

To me, this looks good. Haven't tested it out though, also not sure how one might test this.

On a system without ca-derivations, enable ca-derivations and see if they work.

@Ericson2314
Copy link
Member

I don't yet fully understand the full lifecycle here.

For example:

  1. What does one do if they need to make a "breaking" change to the CA schema while its experimental? It is non-breaking from the non-experimental status quo, but breaking from the last CA change.

  2. What does one do if CA derivations is merged (not experimental) and then we make some sort of cross-cutting breaking change?

I think what this change is doing is grafting on a powerset of feature names in top of the last breaking migration, but I don't think that is sufficient to make this sustainable.

@Mic92
Copy link
Member

Mic92 commented Nov 19, 2024

I don't yet fully understand the full lifecycle here.

For example:

1. What does one do if they need to make a "breaking" change to the CA schema while its experimental? It is non-breaking from the non-experimental status quo, but breaking from the last CA change.

2. What does one do if CA derivations is merged (not experimental) and then we make some sort of cross-cutting breaking change?

I think what this change is doing is grafting on a powerset of feature names in top of the last breaking migration, but I don't think that is sufficient to make this sustainable.

We should not break the schema, experimental or not. We would append a migration after 20220326-ca-derivations if we need to update it. And when we remove the experimental feature status we will remove the if statement and apply this migration unconditionally. If we drop the feature, we would just ignore those extra columns that some nix installations might have in their database. Of course we need to make sure that we don't have different experimental features that introduce conflicting schemas, but we need to make sure this doesn't happen in any case.

@Ericson2314
Copy link
Member

Ericson2314 commented Nov 19, 2024

@Mic92 Agreed. my understanding is this fine-grained approach assumes each named migration is independent of any other. It works for 2^n schemas freely generated by n non-conflicted migrations, but breaks down for when the partial order is not such a free semi-lattice (power set).

@Mic92
Copy link
Member

Mic92 commented Nov 20, 2024

@Mic92 Agreed. my understanding is this fine-grained approach assumes each named migration is independent of any other. It works for 2^n schemas freely generated by n non-conflicted migrations, but breaks down for when the partial order is not such a free semi-lattice (power set).

Well assuming we don't go crazy with experimental features, we should be able to test all combinations of migrations.


std::set<std::string> schemaMigrations;

{
Copy link
Member

@Ericson2314 Ericson2314 Nov 20, 2024

Choose a reason for hiding this comment

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

Suggested change
{
// Load all the names of the migrations we have already done
{

schemaMigrations.insert(useQuerySchemaMigrations.getStr(0));
}

auto doUpgrade = [&](const std::string & migrationName, const std::string & stmt)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
auto doUpgrade = [&](const std::string & migrationName, const std::string & stmt)
// Do a migration if it is not already done.
auto doUpgrade = [&](const std::string & migrationName, const std::string & stmt)

Comment on lines -98 to -109
static int getSchema(Path schemaPath)
{
int curSchema = 0;
if (pathExists(schemaPath)) {
auto s = readFile(schemaPath);
auto n = string2Int<int>(s);
if (!n)
throw Error("'%1%' is corrupt", schemaPath);
curSchema = *n;
}
return curSchema;
}
Copy link
Member

Choose a reason for hiding this comment

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

N.B. this was just inlined.

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.

Whoops I was thinking this was more advanced than it was (but less advanced than it need to be).

I see right now it's just memoization of schemas, and the logic of what to migrate (including dependencies) is out of scope. That's fine!

@Ericson2314 Ericson2314 merged commit 82f6fba into NixOS:master Nov 20, 2024
@edolstra edolstra deleted the schema-migrations branch November 21, 2024 10:32
@nixos-discourse
Copy link

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

https://discourse.nixos.org/t/2024-11-20-nix-team-meeting-minutes-196/56688/1

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

Labels

store Issues and pull requests concerning the Nix store

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants