rembrembdocs

How to reconcile the migration history after applying a hotfix or patch to a production environment.

Patching or hotfixing a database involves making an often time critical change directly in production. For example, you might add an index directly to a production database to resolve an issue with a slow-running query.

Patching the production database directly results in schema drift: your database schema has 'drifted away' from the source of truth, and is out of sync with your migration history. You can use the prisma migrate resolve command to reconcile your migration history without having to remove and re-apply the hotfix with prisma migrate deploy.

Reconciling your migration history with a patch or hotfix

The following scenario assumes that you made a manual change in production and want to propagate that change to your migration history and other databases.

To reconcile your migration history and database schema in production:

migrations/
└─ 20210316150542_retroactively_add_index/
└─ migration.sql

Your database is now in sync with your schema.

✔ Generated Prisma Client (2.19.0-dev.29) to .\node_modules\@prisma\client in 190ms

This command adds the migration to the migration history table without running the actual SQL.

A migration might fail if:

Each migration in the _prisma_migrations table has a logs column that stores the error.

There are two ways to deal with failed migrations in a production environment:

Option 1: Mark the migration as rolled back and re-deploy

The following example demonstrates how to roll back a migration, optionally make changes to fix the issue, and re-deploy:

If you modify the migration, make sure you copy it back to source control to ensure that state of your production database is reflected exactly in development.

Option 2: Manually complete migration and resolve as applied

The following example demonstrates how to manually complete the steps of a migration and mark that migration as applied.

To help with fixing a failed migration, Prisma ORM provides the following commands for creating and executing a migration file:

This section gives an example scenario of a failed migration, and explains how to use migrate diff and db execute to fix it.

Example of a failed migration

Imagine that you have the following User model in your schema, in both your local development environment and your production environment:

schema.prisma

model User {
  id   Int    @id
  name String
}

At this point, your schemas are in sync, but the data in the two environments is different.

You then decide to make changes to your data model, adding another Post model and making the name field on User unique:

schema.prisma

model User {
  id    Int     @id
  name  String  @unique
  email String?
}

model Post {
  id    Int    @id
  title String
}

You create a migration called 'Unique' with the command npx prisma migrate dev -n Unique which is saved in your local migrations history. Applying the migration succeeds in your dev environment and now it is time to release to production.

Unfortunately this migration can only be partially executed. Creating the Post model and adding the email column succeeds, but making the name field unique fails with the following error:

ERROR 1062 (23000): Duplicate entry 'paul' for key 'User_name_key'

This is because there is non-unique data in your production database (e.g. two users with the same name).

You now need to recover manually from the partially executed migration. Until you recover from the failed state, further migrations using prisma migrate deploy are impossible.

At this point there are two options, depending on what you decide to do with the non-unique data:

Moving backwards and reverting all changes

In this case, you need to create a migration that takes your production database to the state of your data model before the last migration.

Your local migration history now yields the same result as the state your production database is in. You can now modify the datamodel again to create a migration that suits your new understanding of the feature you're working on (with non-unique names).

Moving forwards and applying missing changes

In this case, you need to fix the non-unique data and then go ahead with the rest of the migration as planned:

This will create a SQL script file containing all changes necessary to take your production environment from its current failed state to the target state defined in your schema.prisma file.

This applies the changes in the SQL script against the target database without interacting with the migrations table.

This will mark the failed migration called 'Unique' in the migrations table on your production environment as applied.

Your local migration history now yields the same result as the state your production environment is in. You can now continue using the already known migrate dev /migrate deploy workflow.

You might see the following error if you attempt to run Prisma Migrate commands in an environment that uses PgBouncer for connection pooling:

Error: undefined: Database error
Error querying the database: db error: ERROR: prepared statement "s0" already exists

See Prisma Migrate and PgBouncer workaround for further information and a workaround. Follow GitHub issue #6485 for updates.