Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dirty database version 1. Fix and force version #282

Closed
duyanghao opened this issue Sep 4, 2019 · 27 comments
Closed

Dirty database version 1. Fix and force version #282

duyanghao opened this issue Sep 4, 2019 · 27 comments
Labels
wontfix This will not be worked on

Comments

@duyanghao
Copy link

the error appears as below when migrate timeout:

Dirty database version 1. Fix and force version

Steps to Reproduce
Steps to reproduce the behavior:

  1. do migrate timeout
  2. migrate again

Expected Behavior
migrate again could automatically solve this problem and do migrate normally.

@dhui
Copy link
Member

dhui commented Sep 9, 2019

Timeouts may occur and the correct fix is not obvious, so user intervention is necessary.
e.g. The migration could have never applied, partially applied, or fully applied

@duyanghao
Copy link
Author

@dhui How to fix Dirty database status? Is there any documents for this?

@christopher-kleine
Copy link

@duyanghao Force to a previous version and then run "up" again.

So if you get an error in version 10, fix the error and then force it to version 9. Afterwards you can migrate again.

@duyanghao
Copy link
Author

duyanghao commented Sep 12, 2019

@duyanghao Force to a previous version and then run "up" again.

So if you get an error in version 10, fix the error and then force it to version 9. Afterwards you can migrate again.

@anihex Could you please give an example of fixing Dirty database status as described above?

@christopher-kleine
Copy link

@duyanghao Of course I can.

Let's assume I want to create a new table. But I made a "slight" mistake (missing Primary Key).

BEGIN;

CREATE TABLE auth_users (
	id BIGSERIAL,

	name VARCHAR(255),
	superior_id BIGINT REFERENCES auth_users
);

COMMIT;

Now I try to migrate it:

migrate -path migrations/ -database postgres://test:test@localhost/dummy?sslmode=disable up

migrate will refuse this:

error: 2 errors occurred:
	* migration failed: there is no primary key for referenced table "auth_users" in line 0: BEGIN;

CREATE TABLE auth_users (
	id BIGSERIAL,

	name VARCHAR(255),
	superior_id BIGINT REFERENCES auth_users
);

COMMIT;
 (details: pq: there is no primary key for referenced table "auth_users")
	* pq: current transaction is aborted, commands ignored until end of transaction block in line 0: SELECT pg_advisory_unlock($1)

Now I fixed it and added the PRIMARY KEY to the migration:

BEGIN;

CREATE TABLE auth_users (
	id BIGSERIAL PRIMARY KEY,

	name VARCHAR(255),
	superior_id BIGINT REFERENCES auth_users
);

COMMIT;

If I try to migrate again, migrate will STILL refuse:

error: Dirty database version 16. Fix and force version.

So I have to go the last successfull version, which is 15.

migrate -path migrations/ -database postgres://test:test@localhost/dummy?sslmode=disable force 15

If i migrate again, the output will now be:

16/u create_auth_users (17.608619ms)

The same works if you want to go down. But if would be 17 in this case, not 15.
I hope this helps a bit.

@duyanghao
Copy link
Author

@duyanghao Of course I can.

Let's assume I want to create a new table. But I made a "slight" mistake (missing Primary Key).

BEGIN;

CREATE TABLE auth_users (
	id BIGSERIAL,

	name VARCHAR(255),
	superior_id BIGINT REFERENCES auth_users
);

COMMIT;

Now I try to migrate it:

migrate -path migrations/ -database postgres://test:test@localhost/dummy?sslmode=disable up

migrate will refuse this:

error: 2 errors occurred:
	* migration failed: there is no primary key for referenced table "auth_users" in line 0: BEGIN;

CREATE TABLE auth_users (
	id BIGSERIAL,

	name VARCHAR(255),
	superior_id BIGINT REFERENCES auth_users
);

COMMIT;
 (details: pq: there is no primary key for referenced table "auth_users")
	* pq: current transaction is aborted, commands ignored until end of transaction block in line 0: SELECT pg_advisory_unlock($1)

Now I fixed it and added the PRIMARY KEY to the migration:

BEGIN;

CREATE TABLE auth_users (
	id BIGSERIAL PRIMARY KEY,

	name VARCHAR(255),
	superior_id BIGINT REFERENCES auth_users
);

COMMIT;

If I try to migrate again, migrate will STILL refuse:

error: Dirty database version 16. Fix and force version.

So I have to go the last successfull version, which is 15.

migrate -path migrations/ -database postgres://test:test@localhost/dummy?sslmode=disable force 15

If i migrate again, the output will now be:

16/u create_auth_users (17.608619ms)

The same works if you want to go down. But if would be 17 in this case, not 15.
I hope this helps a bit.

@anihex Thank for your reply, that really helps a lot.

@bkakadiya42
Copy link

Maybe I am missing something here. If we are running migrations within a transaction, why do we need to mark the database as dirty? Asking this because it slows down rapid iterations on the migration if the developer has to force after every failure, and when it is the very first migration you can't force it to the version 000000

@ann-kilzer
Copy link

@bkakadiya42 I had the same issue, ended up resetting my entire DB to start clean and then fix my migration file. Hope that helps!

@warent
Copy link

warent commented Aug 3, 2020

It helps bandaid the problem, but it still leaves the question open why a failed transaction makes the database dirty. This must be a bug. The "force" UX is also very user hostile.

@tiagosimao
Copy link

Maybe I am missing something here. If we are running migrations within a transaction, why do we need to mark the database as dirty? Asking this because it slows down rapid iterations on the migration if the developer has to force after every failure, and when it is the very first migration you can't force it to the version 000000

Spot on. Error on first migration seems irrecoverable through migrate's interface. I will hack away and drop the schema_migrations table (if dirty && Version==1) but this is clearly an abstraction violation.
Also, all of this is just silly when using Postgres (or any other db with transaction support in schema changes for that matter)

Didn't understood why the issue is marked as resolved, even the initial question refers to error on version 1 but all answers just seem to ignore that detail. Maybe I'm missing something as well. The docs don't seem to scratch this itch tough.

Some possible ways this lib could help the developer in tackling this corner case I can think of:

  • Allowing disabling the dirty feature
  • Adding method to drop schema_migrations table
  • Never setting first version as dirty (probably incoherent, bad idea)

All for helping out, just didn't fully understood if this is something recognized as a problem.
I really (really) don't want to sound like a jerk, but this bug makes the lib unusable in production. I cannot have an application that out of the blue requires a human messing with the DB.

Cheerio!

@nnachefski
Copy link

nnachefski commented Sep 3, 2020

I'm hitting this while deploying harbor with the kube operator.

2020-09-03T14:39:47Z [INFO] [/common/dao/pgsql.go:127]: Upgrading schema for pgsql ...
2020-09-03T14:39:47Z [ERROR] [/common/dao/pgsql.go:132]: Failed to upgrade schema, error: "Dirty database version 10. Fix and force version."
2020-09-03T14:39:47Z [FATAL] [/core/main.go:123]: failed to migrate: Dirty database version 10. Fix and force version.

@dhui
Copy link
Member

dhui commented Sep 4, 2020

If we are running migrations within a transaction, why do we need to mark the database as dirty?

still leaves the question open why a failed transaction makes the database dirty

migrate does not enforce this (e.g. does not run all migrations in a transaction) so it cannot automatically rollback upon failure. If all of your migrations are wrapped in a transaction, then you can safely force the migration to the previous applied migration. Otherwise, you'll need to inspect the state of your db and determine how to proceed.

The "force" UX is also very user hostile.

Even if migrate were able to rollback failed migration, user intervention is likely required to fix some state for a successful migration. e.g. re-running the same migration with the same starting state won't succeed
Letting the developer/sysadmin know that something is broken and requires their attention and having them acknowledge that the issue has been resolved is a good thing. However, I agree that the UX could be smoother. e.g. forcing is an extra step vs just trying to re-apply the migration

@dhui
Copy link
Member

dhui commented Sep 4, 2020

@nnachefski This looks like an issue with harbor please find/file an issue there.
FWIW, here's their migrations

@mnvx
Copy link

mnvx commented Feb 24, 2021

I agree with @tiagosimao, would be great to have option

Allowing disabling the dirty feature

It is not handy to work with dirty migrations on production. In my case migrations executes from docker container with code.

  • This container cant start until migrations are successfully executed.
  • So it is not possible to run force command in this container.
  • I see here two ways and they are both bad (because it is a bit of hell for admins and more large time of services unavailability):
    • adapt ci/cd processes to support force command,
    • change version directly in database

And my database is Posgtes where DDL queries are support transactions... So best way in my case is as said above

Allowing disabling the dirty feature

@xrn
Copy link

xrn commented Mar 23, 2021

Regarding that topic also I would like to speak following:

If my migration failed during the Down execution - let's say I would like to rollback step 5 and back to migration 4 and it crash. I will see Dirty database version 5. Fix and force version - Without information regarding the direction even if I am using transactions for each migration I do not know if I should force it to version 4 (this will be a case for broken Up) or force it to version 5 (broken Down)

Currently, there is a blocker for new migrations if there is a dirty flag - thanks to that we can not mess up with db state (making several up and down). What do you think about adding information about the direction which caused that dirty state? Thanks to that user can automate forcing to correct version if is sure that is using transactions. It will be very helpful IMO

@joncodo
Copy link

joncodo commented Dec 16, 2021

If the admins can make a decision here, I will implement it. This is really not a good design and is blocking new users from adoption.

2021/12/15 22:28:06 Applying all down migrations
2021/12/15 22:28:06 error: Dirty database version 1. Fix and force version.

@kskenyon
Copy link

I'm trying to install Chirpstack with Postgresql on Debian Buster. I'll be danged if I can get past this error when starting the application-server.

level=fatal msg="setup storage error: storage: migrate up error: Dirty database version 27. Fix and force version."

No idea what to do and where to do it. This must be a common problem. Golang related?

@joncodo
Copy link

joncodo commented Jan 14, 2022

I'm trying to install Chirpstack with Postgresql on Debian Buster. I'll be danged if I can get past this error when starting the application-server.

level=fatal msg="setup storage error: storage: migrate up error: Dirty database version 27. Fix and force version."

No idea what to do and where to do it. This must be a common problem. Golang related?

Try this readme I made for our project: https://github.com/merico-dev/lake/blob/migrations-v2/MIGRATIONS.md

@kskenyon
Copy link

kskenyon commented Jan 14, 2022 via email

@buraksecer
Copy link

buraksecer commented May 26, 2022

the error appears as below when migrate timeout:

Dirty database version 1. Fix and force version

Steps to Reproduce Steps to reproduce the behavior:

  1. do migrate timeout
  2. migrate again

Expected Behavior migrate again could automatically solve this problem and do migrate normally.

If you use docker for database, you have to clear database volumes, this is working for me.

@CodeNinjaUG
Copy link

CodeNinjaUG commented Jun 3, 2022

this is what worked for me
migrate -path db/migrations -database "postgresql://root:8bdc7axyzex@localhost:5432/simple_bank?sslmode=disable" force 1

i had to even drop a database for it work.. but the force version works well

@aksenof
Copy link

aksenof commented Nov 16, 2022

i resolved this error by inserting version with zero dirty flag in the database

in my case, my database name was "schema"

so, check the dirty version:

SELECT * FROM schema_migrations;

in the output i found version = 1 and dirty = 1 and sequence = 1666689290970899911

then i insert new data:

INSERT INTO schema_migrations(version, dirty, sequence) VALUES (1, 0, 1666689299985899911);

congratulations, problem solved!

note: sequence - it's a current datetime in nanoseconds, so, you need the new sequence is larger than the previous one

@dominikbraun
Copy link

Sorry to be so pointed, but if this is really by design, the design is wrong.

@idc77
Copy link

idc77 commented Feb 22, 2023

I'm getting

Error running migration: Dirty database version 2. Fix and force version.

with v1.5.4

I have no idea what the previous version was or what to do. Help?

edit: sorry, this is posted in the wrong repo... I was using shiori.

@cxMoonGlade
Copy link

this is what worked for me migrate -path db/migrations -database "postgresql://root:8bdc7axyzex@localhost:5432/simple_bank?sslmode=disable" force 1

i had to even drop a database for it work.. but the force version works well

Works for me. The hint maybe close every db management application before run the migrate verbose up.
The first version is dirty, which is funny.

@tanishasri22
Copy link

I'm getting

Error running migration: Dirty database version 2. Fix and force version.

with v1.5.4

I have no idea what the previous version was or what to do. Help?

edit: sorry, this is posted in the wrong repo... I was using shiori.

@idc77 can you post redirect to the error you mentioned, if you managed to get the solution?

@crackc0der
Copy link

Can I get more details about "Dirty database"?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests