Swap deployment_merge_requests columns to bigint
What does this MR do and why?
Final step of the bigint conversion for deployment_merge_requests. Two post-deployment migrations, milestone 19.5.
ValidateDeploymentMergeRequestsBigintFks (20260914090001) synchronously validates three foreign keys on the shadow columns:
| Column | Constraint |
|---|---|
deployment_id_convert_to_bigint |
fk_rails_dcbce9f4df_tmp |
merge_request_id_convert_to_bigint |
fk_rails_86a6d8bf12_tmp |
environment_id_convert_to_bigint |
fk_a064ff4453_tmp |
All three are already validated on GitLab.com, confirmed via pg_constraint.convalidated, so this is a no-op there. It exists so self-managed instances reach the same state before the swap, which assumes validated foreign keys. Guarded by skip_bigint_migration?. down is a no-op, since leaving them validated is safe.
SwapColumnsForDeploymentMergeRequestsBigintConversion (20260914090002) swaps deployment_id, merge_request_id, and environment_id with their _convert_to_bigint counterparts inside with_lock_retries(raise_on_exhaustion: true).
| Object type | Swapped |
|---|---|
| Defaults | The 0 defaults stay with the retired integer columns |
| Primary key | deployment_merge_requests_pkey, rebuilt from the prepared bigint index |
| Indexes | idx_environment_merge_requests_unique_index, index_deployment_merge_requests_on_merge_request_id |
| Foreign keys | fk_rails_dcbce9f4df, fk_rails_86a6d8bf12, fk_a064ff4453, each with its _tmp counterpart |
Three points for the reviewer:
-
Primary key index name. The prepared bigint index was created under the hash of
deployment_merge_requests_on_deployment_id_merge_request_id_pkey, not of the real constraint namedeployment_merge_requests_pkey. That came from the async index preparation migration20251110180845. The swap resolves it from that source name, held inPRIMARY_KEY_SOURCE_NAME. -
restore_primary_key_indexplacement.updoes not call it. It relies on the prepared index, which is present and valid on GitLab.com, and fails loudly if missing rather than building a large unique index during the swap.downcalls it twice: before the swap to provide the index that becomes the restored integer primary key, and after to leavebigint_idx_dd999be21656bf3d4bccbehind. Replacing the primary key consumes the index, unlike the secondary indexes, which are renamed in pairs. -
Wraparound check scope. The check covers only
deployment_merge_requests, notdeployments,merge_requests, orenvironments. This migration only renames existing foreign key constraints, which locks just the constrained table. Creating a foreign key locks both sides, and that already happened in !252939 (merged). On detection the migration raises rather than skips, because a skipped swap is still recorded as run.
Both triggers are retained: trigger_b472fca0a1da synchronizes the shadow columns, trigger_cfbec3f07e2b maintains the project_id sharding key. reset_all_trigger_functions runs after the renames.
Each index swap uses swap_index_if_exists. swap_indexes raises when either index is missing, which would abort the whole swap. Earlier conversions hit this in production.
db/structure.sql is unchanged. New installations already start from bigint, so both migrations are no-ops against the canonical schema.
References
- Work item: #581430 (closed)
- Queued the async validation: !253469 (merged)
- Created the replacement foreign keys and bigint indexes: !252939 (merged)
How to set up and validate locally
- Run
./scripts/regenerate-schemaand confirmdb/structure.sqlis unchanged. - Note that the canonical schema has no shadow columns, so step 1 only proves the no-op path.
db:gitlabcom-database-testingis the meaningful verification. - For a real exercise, build a production-shaped copy of the table: integer canonical columns, bigint shadow columns with
0defaults, the three prepared bigint indexes, all six foreign keys, and both triggers. Runup,down, thenupagain.
Result of that run: after up, canonical columns are bigint, shadow columns hold the old integer type, the 0 defaults sit on the retired integer columns, canonical index and foreign key names point at the bigint columns, and both triggers are present. After down, the original schema is restored exactly, including bigint_idx_dd999be21656bf3d4bcc. The second up matched the first.
RuboCop, ruby -c, and scripts/validate_migration_checksum all pass. Reek warnings match the baseline of comparable existing swap migrations.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.