From 9f5c75418832f855fa2f037f2341885d2aaeab4a Mon Sep 17 00:00:00 2001 From: Dylan Griffith <dyl.griffith@gmail.com> Date: Wed, 12 Mar 2025 09:03:34 +0000 Subject: [PATCH] Cleanup migrations adding merge_request_diff_files.project FK This foreign key caused the incident https://gitlab.com/gitlab-com/gl-infra/production/-/issues/19474 . It was added in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/177799 . The problem is that we added a foreign key before adding an index. This means that all statements like `DELETE FROM projects ...` will need to scan the entire `merge_request_diff_files` table to check if the foreign key is valid. This was causing timeouts. In order to resolve the incident we've already manually deleted this migration on GitLab.com . This MR additionally adds another migration to remove the foreign key to clean up any environments where this migration may have already run. --- ..._project_id_to_merge_request_diff_files.rb | 8 +++++++- ...ect_id_fk_from_merge_request_diff_files.rb | 20 +++++++++++++++++++ db/schema_migrations/20250312061803 | 1 + db/structure.sql | 3 --- spec/db/schema_spec.rb | 2 +- 5 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 db/migrate/20250312061803_remove_project_id_fk_from_merge_request_diff_files.rb create mode 100644 db/schema_migrations/20250312061803 diff --git a/db/migrate/20250224231330_add_project_id_to_merge_request_diff_files.rb b/db/migrate/20250224231330_add_project_id_to_merge_request_diff_files.rb index c3efa0dabe8ea..d4a02faf30c0c 100644 --- a/db/migrate/20250224231330_add_project_id_to_merge_request_diff_files.rb +++ b/db/migrate/20250224231330_add_project_id_to_merge_request_diff_files.rb @@ -16,7 +16,13 @@ def up add_column SOURCE_TABLE, :project_id, :bigint, if_not_exists: true end - add_concurrent_foreign_key SOURCE_TABLE, :projects, column: :project_id, on_delete: :cascade + # This caused the incident https://gitlab.com/gitlab-com/gl-infra/production/-/issues/19474 + # We must first add the index before adding a foreign key. We also explicitly removed it in + # db/post_migrate/20250312061803_remove_project_id_fk_from_merge_request_diff_files.rb to clean up any installations + # that ran this. + # + # no-op: + # add_concurrent_foreign_key SOURCE_TABLE, :projects, column: :project_id, on_delete: :cascade end def down diff --git a/db/migrate/20250312061803_remove_project_id_fk_from_merge_request_diff_files.rb b/db/migrate/20250312061803_remove_project_id_fk_from_merge_request_diff_files.rb new file mode 100644 index 0000000000000..705cbf8e2f5a6 --- /dev/null +++ b/db/migrate/20250312061803_remove_project_id_fk_from_merge_request_diff_files.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +class RemoveProjectIdFkFromMergeRequestDiffFiles < Gitlab::Database::Migration[2.2] + milestone '17.10' + + disable_ddl_transaction! + + FK_NAME = 'fk_0e3ba01603' + + def up + with_lock_retries do + remove_foreign_key_if_exists(:merge_request_diff_files, :projects, name: FK_NAME, reverse_lock_order: true) + end + end + + def down + # no-op + # we won't add this again, as it may create problems without an index + end +end diff --git a/db/schema_migrations/20250312061803 b/db/schema_migrations/20250312061803 new file mode 100644 index 0000000000000..c8518ffaa1147 --- /dev/null +++ b/db/schema_migrations/20250312061803 @@ -0,0 +1 @@ +c643bd5a8781d57cf943170020f44972ad0e06faa1f602b80409eea7704310ee \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 893f765bddbc4..e320d2edfdfe8 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -39401,9 +39401,6 @@ ALTER TABLE ONLY subscription_user_add_on_assignments ALTER TABLE ONLY approval_project_rules_users ADD CONSTRAINT fk_0dfcd9e339 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; -ALTER TABLE ONLY merge_request_diff_files - ADD CONSTRAINT fk_0e3ba01603 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; - ALTER TABLE ONLY ci_runner_projects ADD CONSTRAINT fk_0e743433ff FOREIGN KEY (runner_id) REFERENCES ci_runners_archived(id) ON DELETE CASCADE; diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb index 7e5ee95a09b77..71e1bcaa45a32 100644 --- a/spec/db/schema_spec.rb +++ b/spec/db/schema_spec.rb @@ -31,7 +31,6 @@ ci_sources_pipelines: [%w[source_partition_id source_pipeline_id], %w[partition_id pipeline_id]], ci_sources_projects: [%w[partition_id pipeline_id]], # index on pipeline_id is sufficient ci_stages: [%w[partition_id pipeline_id]], # the index on pipeline_id is sufficient - merge_request_diff_files: [%w[project_id]], # async index to be created - https://gitlab.com/gitlab-org/gitlab/-/issues/523103 notes: %w[namespace_id], # this index is added in an async manner, hence it needs to be ignored in the first phase. p_ci_build_trace_metadata: [%w[partition_id build_id], %w[partition_id trace_artifact_id]], # the index on build_id is enough p_ci_builds: [%w[partition_id stage_id], %w[partition_id execution_config_id], %w[auto_canceled_by_partition_id auto_canceled_by_id], %w[upstream_pipeline_partition_id upstream_pipeline_id], %w[partition_id commit_id]], # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/142804#note_1745483081 @@ -172,6 +171,7 @@ merge_request_cleanup_schedules: %w[project_id], merge_requests_compliance_violations: %w[target_project_id], merge_request_diffs: %w[project_id], + merge_request_diff_files: %w[project_id], merge_request_diff_commits: %w[commit_author_id committer_id], # merge_request_diff_commits_b5377a7a34 is the temporary table for the merge_request_diff_commits partitioning # backfill. It will get foreign keys after the partitioning is finished. -- GitLab