diff options
Diffstat (limited to 'doc/development/migration_style_guide.md')
-rw-r--r-- | doc/development/migration_style_guide.md | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md index 0bd9979e790..d85b7372814 100644 --- a/doc/development/migration_style_guide.md +++ b/doc/development/migration_style_guide.md @@ -162,6 +162,9 @@ def down end ``` +Migrations like this are inherently risky and [additional actions](database_review.md#preparation-when-adding-data-migrations) +are required when preparing the migration for review. + ## Atomicity By default, migrations are single transaction. That is, a transaction is opened @@ -769,6 +772,32 @@ to run on a large table, as long as it is only updating a small subset of the rows in the table, but do not ignore that without validating on the GitLab.com staging environment - or asking someone else to do so for you - beforehand. +## Removing a foreign key constraint + +When removing a foreign key constraint, we need to acquire a lock on both tables +that are related to the foreign key. For tables with heavy write patterns, it's a good +idea to use `with_lock_retries`, otherwise you might fail to acquire a lock in time. +You might also run into deadlocks when acquiring a lock, because ordinarily +the application writes in `parent,child` order. However, removing a foreign +key acquires the lock in `child,parent` order. To resolve this, you can +explicitly acquire the lock in `parent,child`, for example: + +```ruby +disable_ddl_transaction! + +def up + with_lock_retries do + execute('lock table ci_pipelines, ci_builds in access exclusive mode') + + remove_foreign_key :ci_builds, to_table: :ci_pipelines, column: :pipeline_id, on_delete: :cascade, name: 'the_fk_name' + end +end + +def down + add_concurrent_foreign_key :ci_builds, :ci_pipelines, column: :pipeline_id, on_delete: :cascade, name: 'the_fk_name' +end +``` + ## Dropping a database table Dropping a database table is uncommon, and the `drop_table` method |