You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Now follow the same steps as for the first reproduction: apply the first migration, generate load, apply the second migration. The second migration will likely fail with the same error as in the first reproduction.
Notes
In the first reproduction, the operation fails because there is a race between the movies_name_unique index being marked valid after it is created (concurrently) on operation Start:
We can maybe have a check that periodically looks into catalog table pg_index to see if the index is validated or not. So that we can wait until it is validated, before returning.
Alternatively we can use the postgres view pg_stat_progress_analyze. I haven't use that before but it could maybe be helpful for these cases.
One other thing that comes to my mind is to introduce a locking mechanism to prevent the race, but feels like it could be an overkill.
Regarding the Slack discussion of this issue:
The best is to wait until the index is valid and return and error if index is not created successfully, this implies other problems (violation of unique constraints, deadlock etc).
I agree with Andrew:
Maybe the pg_stat_progress_create_index table can be queried to find out if Postgres is still working on the index or has given up. (@andrew-farries )
In the case we get error, the right action imo, is not reindexing but dropping the invalid index and re-running create index concurrently.
There is a race condition when adding a
unique
constraint to a column.The race can cause the operation to fail, particularly when the target database is under high load at the time of the migration.
Reproduction 1
Create a pair of migrations:
01_create_table.json
02_set_unique.json
Apply the first migration:
In the target database, generate some load on the system:
While the above
INSERT
operation is running, apply the second migration:The second migration is likely to fail with the following error:
Reproduction 2
The same problem also exists when a column with a
UNIQUE
constraint is duplicated, for example to change the nullability of the column. To reproduce:Create a pair of migrations:
01_create_table.json
02_set_notnull.json
Now follow the same steps as for the first reproduction: apply the first migration, generate load, apply the second migration. The second migration will likely fail with the same error as in the first reproduction.
Notes
In the first reproduction, the operation fails because there is a race between the
movies_name_unique
index being marked valid after it is created (concurrently) on operationStart
:pgroll/pkg/migrations/op_set_unique.go
Lines 74 to 84 in 6d48386
and when the unique constraint is added using the index on operation
Complete
:pgroll/pkg/migrations/op_set_unique.go
Lines 35 to 47 in 6d48386
In the second reproduction, the race is between the concurrent index creation performed by the column duplicator:
pgroll/pkg/migrations/duplicate.go
Lines 170 to 186 in 6d48386
And when the unique constraint is created using the index when the column is renamed on operation complete:
pgroll/pkg/migrations/rename.go
Lines 123 to 159 in 6d48386
In both cases the correct behaviour is to wait for the concurrently created index to be marked as valid before returning.
The text was updated successfully, but these errors were encountered: