Swap issues bigint columns batch one
What does this MR do and why?
Swaps the first batch of issues integer ID columns to their bigint counterparts, as part of the conversion tracked in #629827 (closed).
The prerequisites for this batch are already merged: the bigint indexes were prepared asynchronously (!251347 (merged)) and created synchronously (!253447 (merged)), and the foreign keys were added and validated (!253725 (merged)). This MR performs the swap and cleans up the temporary objects.
Columns swapped (6)
closed_by_id, duplicated_to_id, last_edited_by_id, moved_to_id, promoted_to_epic_id, updated_by_id
id, project_id, milestone_id, and author_id are not in this batch — they are coupled through composite indexes and handled in later batches.
Migrations
| Migration | Action |
|---|---|
20260916090001 |
Swap the six columns, indexes, and foreign keys (single transaction) |
20260916090002 |
Drop fk_c63cbf6c25_tmp (closed_by_id → users) |
20260916090003 |
Drop fk_9c4516d665_tmp (duplicated_to_id → issues) |
20260916090004 |
Drop fk_a194299be1_tmp (moved_to_id → issues) |
20260916090005 |
Drop fk_df75a7c8b8_tmp (promoted_to_epic_id → epics) |
20260916090006 |
Drop fk_ffed080f01_tmp (updated_by_id → users) |
20260916090007 |
Drop the six temporary bigint_idx_* indexes |
The swap (20260916090001)
In a single with_lock_retries transaction it swaps the six columns with their *_convert_to_bigint counterparts, resets the sync trigger, swaps the 6 indexes (canonical name bigint_idx_*), and swaps the 5 foreign keys (canonical name *_tmp). Running everything in one transaction guarantees the schema is never left partially swapped, which is why this step is not split per column.
Cleaning up the temporary objects
After the swap, the bigint_idx_* indexes and *_tmp foreign keys sit on the old integer columns and are removed. Following the bigint conversion guidelines:
- Each temporary foreign key is dropped in its own migration, so one drop failing to acquire its lock does not block the others.
- Foreign keys are dropped before the indexes. A live foreign key with no supporting index makes deletes from the referenced table (
users,issues,epics) time out, so the temporary indexes are removed last.
All migrations are guarded on the conversion columns' existence and type, so they are no-ops on instances that already have native bigint IDs.
Scope
| Item | Count | Notes |
|---|---|---|
| Columns | 6 | none has a column default, so no default swap |
| Indexes | 6 | one per column, no composites |
| Foreign keys | 5 | last_edited_by_id has no FK |
There is no primary key swap in this batch (id is converted later).
Why the backfill assurance helper is omitted
The swap intentionally does not call ensure_backfill_conversion_of_integer_to_bigint_is_finished. That helper checks for a CopyColumnUsingBackgroundMigrationJob record, but the issues bigint columns were backfilled by the custom BackfillIssuesCorrectWorkItemTypeId batched background migration (introduced in !167972 (merged), finalized by 20241030165330). Calling the helper would raise because no matching record exists for this table. The backfill is complete: the sync trigger was created in the same migration as the columns, so every write since has been kept in sync, and the batched background migration backfilled all pre-existing rows.
Migration output
db/structure.sql is unchanged: after the swap the six columns are bigint, which already matches the committed schema, and the temporary indexes/foreign keys live on *_convert_to_bigint columns that are not part of that schema. (Danger flags "new migrations added but db/structure.sql wasn't updated"; this is expected for ID conversions.)
Verification before merge
Confirmed on a production clone that all five temporary foreign keys are VALID and all six bigint_idx_* indexes are valid before the swap.
MR acceptance checklist
- Database review requested — column swap with index and foreign key swaps, plus temporary object cleanup.