마이그레이션 중 다운타임 방지
데이터베이스 작업 시 특정 작업은 다운타임을 요구할 수 있습니다. 마이그레이션 중에는 다운타임이 발생할 수 없기 때문에 다운타임 없이 동일한 최종 결과를 얻기 위해 일련의 단계를 사용해야 합니다. 이 가이드는 다운타임이 필요해 보일 수 있는 다양한 작업과 그 영향, 그리고 다운타임 없이 수행하는 방법을 설명합니다.
열 삭제
열을 제거하는 것은 까다롭습니다. GitLab 프로세스가 이러한 열이 존재할 것으로 기대하기 때문에 ActiveRecord가 테이블 스키마를 캐시하기 때문입니다. 열이 참조되지 않더라도 마찬가지입니다. 열이 명시적으로 무시되지 않으면 발생하는 문제입니다. 이를 안전하게 해결하기 위해서는 세 가지 단계로 세 번의 릴리스를 필요로 합니다:
-
열 무시하기 (릴리즈 M)
-
열 삭제하기 (릴리즈 M+1)
-
무시 규칙 제거하기 (릴리즈 M+2)
열을 삭제하는 것은 쉽게 롤백할 수 없는 파괴적인 작업이기 때문에, 이러한 단계를 세 번의 릴리스를 통해 나누어 수행하는 이유입니다.
이 절차를 따르면 GitLab.com에 배포가 없고 셀프 관리 설치에 대한 업그레이드 프로세스가 이러한 단계를 함께 묶지 않도록 하는 데 도움이 됩니다.
열 무시하기 (릴리즈 M)
첫 번째 단계는 애플리케이션 코드에서 열을 무시하고, 모델 유효성 검사 등을 포함한 모든 코드 참조를 제거하는 것입니다.
이 단계는 Rails가 열을 캐시하고 다양한 곳에서 이 캐시를 재사용하기 때문에 필요합니다. 무시할 열을 정의하여 이를 수행할 수 있습니다. 예를 들어, 릴리즈 12.5
에서 User 모델의 updated_at
을 무시하려면 다음을 사용합니다:
class User < ApplicationRecord
include IgnorableColumns
ignore_column :updated_at, remove_with: '12.7', remove_after: '2019-12-22'
end
여러 열도 무시할 수 있습니다:
ignore_columns %i[updated_at created_at], remove_with: '12.7', remove_after: '2019-12-22'
모델이 CE와 EE 모두에 존재하는 경우, 열은 CE 모델에서 무시되어야 합니다. 모델이 EE에만 존재하는 경우, 해당 모델에 추가해야 합니다.
열 무시 규칙을 제거할 안전한 시점을 표시해야 합니다:
-
remove_with
: 열 무시를 추가한 후 일반적으로 두 개의 릴리스(M+2) 후의 GitLab 릴리즈로 설정합니다 (12.7
이 예제입니다). -
remove_after
: 열 무시를 제거하는 것이 안전하다고 간주되는 날짜로 설정합니다. 일반적으로 M+1 릴리스 날짜 이후, M+2 개발 주기 동안입니다. 예를 들어,12.7
의 개발 주기가2019-12-18
과2020-01-17
사이이므로,12.6
이 열 삭제하기 릴리즈인 만큼12.6
릴리즈 날짜인2019-12-22
로 날짜를 설정하는 것이 안전합니다.
이 정보는 열 무시와 관련된 정보를 더 잘 이해하는 데 도움이 되며, GitLab.com에 대한 일반 릴리스 및 배포 모두에서 열 무시를 너무 일찍 제거하지 않도록 보장합니다. 예를 들어, 열을 무시하는 변경 사항과 이후 열 무시를 제거하는 변경 사항을 포함하여 많은 변경 사항을 배포하여 다운타임이 발생하는 상황을 피할 수 있습니다.
이 예에서는 열 무시 변경 사항이 릴리즈 12.5
에 포함되었습니다.
열 삭제 (릴리즈 M+1)
예제를 계속하여, 열 삭제는 릴리즈 12.6
의 배포 후 마이그레이션으로 진행됩니다:
배포 후 마이그레이션을 생성하는 것으로 시작합니다:
bundle exec rails g post_deployment_migration remove_users_updated_at_column
열을 제거하는 마이그레이션을 작성할 때 다음 시나리오를 고려해야 합니다:
제거된 열에 해당하는 인덱스나 제약 조건이 없음
이 경우, 트랜잭셔널 마이그레이션을 사용할 수 있습니다:
class RemoveUsersUpdatedAtColumn < Gitlab::Database::Migration[2.1]
def up
remove_column :users, :updated_at
end
def down
add_column :users, :updated_at, :datetime
end
end
제거된 열에 해당하는 인덱스나 제약 조건이 있음
down
메서드가 드롭된 인덱스나 제약 조건을 다시 추가해야 하는 경우, 이는 트랜잭셔널 마이그레이션에서 수행할 수 없습니다. 마이그레이션은 다음과 같이 됩니다:
class RemoveUsersUpdatedAtColumn < Gitlab::Database::Migration[2.1]
disable_ddl_transaction!
def up
remove_column :users, :updated_at
end
def down
add_column(:users, :updated_at, :datetime, if_not_exists: true)
# 반드시 `up` 메서드에서 드롭된 인덱스나 제약 조건을 다시 추가해야 합니다.
add_concurrent_index(:users, :updated_at)
end
end
down
메서드에서, 우리는 열이 다시 추가되기 전에 이미 존재하는지 확인합니다.
이는 마이그레이션이 비트랜잭셔널하고 실행 중에 실패했을 수 있기 때문입니다.
disable_ddl_transaction!
는 전체 마이그레이션을 감싸는 트랜잭션을 비활성화하는 데 사용됩니다.
데이터베이스 마이그레이션에 대한 자세한 내용은 마이그레이션 스타일 가이드 페이지를 참조하세요.
무시 규칙 제거 (릴리즈 M+2)
다음 릴리즈인 12.7
에서는 무시 규칙을 제거하기 위한 또 다른 머지 요청을 설정합니다.
이것은 ignore_column
행을 제거하고, 더 이상 필요하지 않은 경우 IgnoreableColumns
의 포함도 제거합니다.
이것은 remove_with
로 표시된 릴리즈와 remove_after
날짜가 지난 후에만 병합되어야 합니다.
열 이름 변경
열 이름을 표준 방법으로 변경하려면 다운타임이 필요합니다.
응용 프로그램이 데이터베이스 마이그레이션 중이거나 그 후에도 이전 열 이름을 계속 사용할 수 있기 때문입니다.
다운타임 없이 열 이름을 변경하려면 두 개의 마이그레이션이 필요합니다: 정규 마이그레이션과 배포 후 마이그레이션.
이 두 마이그레이션은 같은 릴리즈에 포함될 수 있습니다. 단계는 다음과 같습니다:
- 정규 마이그레이션 추가 (릴리즈 M)
- 열 무시 (릴리즈 M)
- 배포 후 마이그레이션 추가 (릴리즈 M)
- 무시 규칙 제거 (릴리즈 M+1)
정기 마이그레이션 추가 (릴리스 M)
먼저 정기 마이그레이션을 생성해야 합니다. 이 마이그레이션은
Gitlab::Database::MigrationHelpers#rename_column_concurrently
를 사용하여
이름을 변경해야 합니다. 예를 들어
# db/migrate에 있는 정기 마이그레이션
class RenameUsersUpdatedAtToUpdatedAtTimestamp < Gitlab::Database::Migration[2.1]
disable_ddl_transaction!
def up
rename_column_concurrently :users, :updated_at, :updated_at_timestamp
end
def down
undo_rename_column_concurrently :users, :updated_at, :updated_at_timestamp
end
end
이는 열 이름을 변경하고, 데이터가 동기화 상태를 유지하며, 인덱스와 외래 키를 복사하는 작업을 처리합니다.
열에 원래 열의 이름이 포함되지 않은 하나 이상의 인덱스가 포함되어 있는 경우, 앞서 설명한 절차가 실패합니다. 이 경우 이러한 인덱스의 이름도 변경해야 합니다.
열 무시 (릴리스 M)
다음 단계는 애플리케이션 코드에서 열을 무시하고 사용되지 않도록 하는 것입니다. 이 단계는 Rails가 열을 캐시하고 다양한 위치에서 이 캐시를 재사용하기 때문에 필요합니다. 이 단계는 열이 삭제될 때의 첫 번째 단계와 유사하며, 동일한 요구 사항이 적용됩니다.
class User < ApplicationRecord
include IgnorableColumns
ignore_column :updated_at, remove_with: '12.7', remove_after: '2019-12-22'
end
배포 후 마이그레이션 추가 (릴리스 M)
이름 변경 절차에는 배포 후 마이그레이션에서 일부 정리가 필요합니다.
다음과 같이
Gitlab::Database::MigrationHelpers#cleanup_concurrent_column_rename
를 사용하여 이 정리를 수행할 수 있습니다:
# db/post_migrate에 있는 배포 후 마이그레이션
class CleanupUsersUpdatedAtRename < Gitlab::Database::Migration[2.1]
disable_ddl_transaction!
def up
cleanup_concurrent_column_rename :users, :updated_at, :updated_at_timestamp
end
def down
undo_cleanup_concurrent_column_rename :users, :updated_at, :updated_at_timestamp
end
end
큰 테이블을 이름 변경하는 경우, 첫 번째 마이그레이션이 실행되었지만 두 번째 정리 마이그레이션이 아직 실행되지 않은 상태를 신중하게 고려해야 합니다. Canary를 사용하면 시스템이 이 상태로 상당한 시간 동안 실행될 수 있습니다.
무시 규칙 제거 (릴리스 M+1)
열이 삭제될 때와 동일하게, 이름 변경이 완료된 후, 후속 릴리스에서 무시 규칙을 제거해야 합니다.
열 제약 조건 변경
NOT NULL
절(또는 다른 제약 조건)을 추가하거나 제거하는 작업은 일반적으로
다운타임 없이 수행할 수 있습니다. 하지만, 이는 모든 애플리케이션
변경 사항이 먼저 배포되어야 함을 요구합니다. 따라서, 열의 제약 조건 변경은
배포 후 마이그레이션에서 발생해야 합니다.
효율적이지 않은 쿼리가 생성되므로 change_column
의 사용은 피해야 합니다.
왜냐하면 이는 전체 열 유형을 다시 정의하기 때문입니다.
각 특정 사용 사례에 대한 지침을 확인할 수 있습니다:
열 형식 변경
열의 형식을 변경하는 것은
Gitlab::Database::MigrationHelpers#change_column_type_concurrently
를 사용하여 수행할 수 있습니다. 이
메서드는 rename_column_concurrently
와 유사하게 작동합니다. 예를 들어, users.username
의 형식을 string
에서 text
로 변경하려고 한다고 가정해 보겠습니다:
정기 마이그레이션 생성
정기 마이그레이션은 임시 이름으로 새로운 열을 생성하고 데이터를 동기화하기 위해 일부 트리거를 설정하는 데 사용됩니다. 이러한 마이그레이션은 다음과 같이 보입니다:
# db/migrate에 있는 정기 마이그레이션
class ChangeUsersUsernameStringToText < Gitlab::Database::Migration[2.1]
disable_ddl_transaction!
def up
change_column_type_concurrently :users, :username, :text
end
def down
undo_change_column_type_concurrently :users, :username
end
end
배포 후 마이그레이션 생성
다음으로 배포 후 마이그레이션을 사용하여 변경 사항을 정리해야 합니다:
# db/post_migrate에 있는 배포 후 마이그레이션
class ChangeUsersUsernameStringToTextCleanup < Gitlab::Database::Migration[2.1]
disable_ddl_transaction!
def up
cleanup_concurrent_column_type_change :users, :username
end
def down
undo_cleanup_concurrent_column_type_change :users, :username, :string
end
end
그리고 끝났습니다!
데이터 유형 변환
일부 유형 변경은 데이터를 새로운 유형으로 변환해야 합니다. 예를 들어 text
에서 jsonb
로 변경할 때입니다. 이 경우 type_cast_function
옵션을 사용하십시오.
나쁜 데이터가 없고 변환이 항상 성공해야 합니다. 변환 오류를 처리하는 사용자 지정 함수를 제공할 수도 있습니다.
예제 마이그레이션:
def up
change_column_type_concurrently :users, :settings, :jsonb, type_cast_function: 'jsonb'
end
열 기본값 변경
열 기본값 변경은 Rails가 기본값과 같은 값을 처리하는 방식 때문에 어렵습니다.
참고: Rails는 레코드를 작성할 때 PostgreSQL에 기본값을 전송하는 것을 무시합니다. 이 작업은 데이터베이스에 맡깁니다. 마이그레이션이 열의 기본값을 변경할 때, 실행 중인 애플리케이션은 스키마 캐시로 인해 이 변경 사항을 인식하지 못합니다. 그러면 애플리케이션은 잘못된 데이터를 데이터베이스에 작성할 위험이 있으며, 특히 데이터베이스 마이그레이션을 실행한 후 오랜 시간이 지나서 새로운 버전의 코드를 배포할 때 더 그렇습니다.
실행 중인 코드가 열의 이전 기본값을 명시적으로 작성하는 경우, INSERT 쿼리에서 이전 기본값을 명시적으로 지정할 때 Rails가 이전 기본값을 새로운 기본값으로 교체하지 않도록 방지하기 위해 다단계 프로세스를 따라야 합니다.
이 작업을 수행하려면 두 개의 마이너 릴리스에서 단계가 필요합니다:
-
모델에
SafelyChangeColumnDefault
관심사를 추가하고 배포 후 마이그레이션에서 기본값을 변경하여야 합니다. -
다음 마이너 릴리스에서
SafelyChangeColumnDefault
관심사를 정리하여야 합니다.
SafelyChangeColumnDefault
를 정리하기 전에 마이너 릴리스를 기다려야 합니다. 자가 관리 릴리스는 전체 마이너 릴리스를 단일 제로 다운타임 배포로 묶기 때문입니다.
SafelyChangeColumnDefault
커넥션을 모델에 추가하고 마이그레이션 후 기본값을 변경합니다.
첫 번째 단계는 애플리케이션 코드에서 열을 변경할 수 있는 안전한 것으로 표시하는 것입니다.
class Ci::Build < ApplicationRecord
include SafelyChangeColumnDefault
columns_changing_default :partition_id
end
그런 다음 기본값을 변경하는 배포 후 마이그레이션을 생성합니다:
bundle exec rails g post_deployment_migration change_ci_builds_default
class ChangeCiBuildsDefault < Gitlab::Database::Migration[2.1]
def change
change_column_default('ci_builds', 'partition_id', from: 100, to: 101)
end
end
다음 소규모 릴리즈에서 SafelyChangeColumnDefault
커넥션 정리
다음 소규모 릴리즈에서 columns_changing_default
호출을 제거하기 위한 새 병합 요청을 생성합니다. 또한 다른 열에 필요하지 않을 경우 SafelyChangeColumnDefault
포함도 제거합니다.
큰 테이블의 스키마 변경
change_column_type_concurrently
및 rename_column_concurrently
는 다운타임 없이 테이블의 스키마를 변경하는 데 사용할 수 있지만, 큰 테이블에는 잘 작동하지 않습니다. 모든 작업이 순차적으로 진행되기 때문에 마이그레이션이 완료되는 데 시간이 매우 오래 걸릴 수 있으며, 배포가 진행되지 못하게 됩니다. 또한 많은 행을 순차적으로 빠르게 업데이트하기 때문에 데이터베이스에 많은 압박을 가할 수 있습니다.
데이터베이스 압박을 줄이기 위해 큰 테이블(예: issues
)의 열을 마이그레이션할 때는 배경 마이그레이션을 사용하는 것이 좋습니다. 배경 마이그레이션은 작업/부하를 더 긴 기간에 걸쳐 분산시키므로 배포가 느려지지 않습니다.
자세한 내용은 배치 배경 마이그레이션 정리에 대한 문서를 참조하세요.
인덱스 추가
add_concurrent_index
를 사용하면 인덱스를 추가하는 데 다운타임이 필요하지 않습니다.
자세한 내용은 마이그레이션 스타일 가이드를 참조하세요.
인덱스 삭제
인덱스를 삭제하는 데 다운타임이 필요하지 않습니다.
테이블 추가
이 작업은 테이블을 사용하는 코드가 아직 없기 때문에 안전합니다.
테이블 삭제
테이블을 삭제하는 것은 배포 후 마이그레이션을 사용하여 안전하게 수행할 수 있지만, 애플리케이션이 더 이상 해당 테이블을 사용하지 않는 경우에만 가능합니다.
db/docs/deleted_tables
에 테이블을 추가하고, 데이터베이스 사전에 설명된 프로세스를 사용하십시오.
테이블이 삭제되더라도 데이터베이스 마이그레이션에서 여전히 참조됩니다.
테이블 이름 변경
테이블 이름 변경은 애플리케이션이 데이터베이스 마이그레이션 중/후에 구 버전의 테이블 이름을 계속 사용할 수 있으므로 다운타임이 필요합니다.
테이블과 ActiveRecord 모델이 아직 사용되지 않는 경우, 기존 테이블을 제거하고 새 테이블을 만드는 것이 “테이블 이름을 변경하는” 선호되는 방법입니다.
다운타임 없이 테이블 이름을 변경하려면 다중 릴리즈 테이블 이름 변경 프로세스를 따르세요.
외래 키 추가
외래 키 추가는 일반적으로 3단계로 진행됩니다:
- 트랜잭션 시작
- 제약 조건을 추가하기 위해
ALTER TABLE
실행 - 모든 기존 데이터 점검
ALTER TABLE
이 일반적으로 트랜잭션 종료까지 독점 잠금을 획득하므로 이 방법은 다운타임이 필요합니다.
GitLab은 Gitlab::Database::MigrationHelpers#add_concurrent_foreign_key
를 사용하여 이를 우회할 수 있도록 허용합니다. 이 방법은 다운타임이 필요하지 않도록 보장합니다.
외래 키 제거
이 작업은 다운타임을 필요로 하지 않습니다.
integer
기본 키를 bigint
로 마이그레이션
일부 테이블에서 integer
기본 키(PK)에 대한 오버플로우 위험을 방지하기 위해 PK를 bigint
로 마이그레이션해야 합니다. 다운타임 없이 데이터베이스에 과부하를 주지 않고 이 작업을 수행하는 과정은 아래에 설명되어 있습니다.
변환 초기화 및 기존 데이터 마이그레이션 시작 (릴리즈 N)
과정을 시작하기 위해 새로운 bigint
열을 생성하는 정기 마이그레이션을 추가합니다. 제공된 initialize_conversion_of_integer_to_bigint
헬퍼를 사용하십시오. 이 헬퍼는 또한 데이터베이스 트리거를 생성하여 새 레코드의 두 열을 동기화합니다 (코드):
# frozen_string_literal: true
class InitializeConversionOfMergeRequestMetricsToBigint < Gitlab::Database::Migration[2.1]
disable_ddl_transaction!
TABLE = :merge_request_metrics
COLUMNS = %i[id]
def up
initialize_conversion_of_integer_to_bigint(TABLE, COLUMNS)
end
def down
revert_initialize_conversion_of_integer_to_bigint(TABLE, COLUMNS)
end
end
새로운 bigint
열은 무시합니다:
# frozen_string_literal: true
class MergeRequest::Metrics < ApplicationRecord
include IgnorableColumns
ignore_column :id_convert_to_bigint, remove_with: '16.0', remove_after: '2023-05-22'
end
기존 데이터를 마이그레이션하기 위해 배치 백그라운드 마이그레이션을 예약합니다 (코드):
# frozen_string_literal: true
class BackfillMergeRequestMetricsForBigintConversion < Gitlab::Database::Migration[2.1]
restrict_gitlab_migration gitlab_schema: :gitlab_main
TABLE = :merge_request_metrics
COLUMNS = %i[id]
def up
backfill_conversion_of_integer_to_bigint(TABLE, COLUMNS, sub_batch_size: 200)
end
def down
revert_backfill_conversion_of_integer_to_bigint(TABLE, COLUMNS)
end
end
배경 마이그레이션 모니터링
마이그레이션이 실행되는 동안 성능을 확인합니다. 이를 수행하는 여러 가지 방법이 아래에 설명되어 있습니다.
배치 배경 마이그레이션의 고수준 상태
배치 배경 마이그레이션 상태 확인 방법을 확인하십시오.
데이터베이스 쿼리
관련 데이터베이스 테이블을 직접 쿼리할 수 있습니다. 읽기 전용 복제본에 대한 접근이 필요합니다. 예시 쿼리:
-- 주어진 테이블에 대한 배치 배경 마이그레이션의 세부정보 가져오기
SELECT * FROM batched_background_migrations WHERE table_name = 'namespaces'\gx
-- 주어진 테이블에 대한 배치 배경 마이그레이션 작업의 상태별 개수 가져오기
SELECT
batched_background_migrations.id, batched_background_migration_jobs.status, COUNT(*)
FROM
batched_background_migrations
JOIN batched_background_migration_jobs ON batched_background_migrations.id = batched_background_migration_jobs.batched_background_migration_id
WHERE
table_name = 'namespaces'
GROUP BY
batched_background_migrations.id, batched_background_migration_jobs.status;
-- 주어진 테이블에 대한 배치 배경 마이그레이션 진행 상황 (추정 총 튜플 수 기준)
SELECT
m.table_name,
LEAST(100 * sum(j.batch_size) / pg_class.reltuples, 100) AS percentage_complete
FROM
batched_background_migrations m
JOIN batched_background_migration_jobs j ON j.batched_background_migration_id = m.id
JOIN pg_class ON pg_class.relname = m.table_name
WHERE
j.status = 3 AND m.table_name = 'namespaces'
GROUP BY m.id, pg_class.reltuples;
Sidekiq 로그
우리는 또한 배치된 백그라운드 마이그레이션을 실행하는 작업자를 모니터링하기 위해 Sidekiq 로그를 사용할 수 있습니다:
-
@gitlab.com
이메일 주소로 Kibana에 로그인합니다. - 인덱스 패턴을
pubsub-sidekiq-inf-gprd*
로 변경합니다. -
json.queue: cronjob:database_batched_background_migration
에 대한 필터를 추가합니다.
PostgreSQL 느린 쿼리 로그
느린 쿼리 로그는 1초 이상 실행된 느린 쿼리를 추적합니다. 배치된 백그라운드 마이그레이션의 경우 이를 보려면:
-
@gitlab.com
이메일 주소로 Kibana에 로그인합니다. - 인덱스 패턴을
pubsub-postgres-inf-gprd*
로 변경합니다. -
json.endpoint_id.keyword: Database::BatchedBackgroundMigrationWorker
에 대한 필터를 추가합니다. - 선택사항. 업데이트만 보려면
json.command_tag.keyword: UPDATE
에 대한 필터를 추가합니다. - 선택사항. 실패한 문장만 보려면
json.error_severity.keyword: ERROR
에 대한 필터를 추가합니다. - 선택사항. 테이블 이름으로 필터를 추가합니다.
Grafana 대시보드
데이터베이스의 상태를 모니터링하기 위해 다음과 같은 추가 메트릭을 사용하십시오:
-
PostgreSQL 튜플 통계: 활성화된 테이블에 대한 업데이트 비율이 높거나 이 테이블의 죽은 튜플 비율이 증가하면
autovacuum
이 따라가지 못할 수 있습니다. - PostgreSQL 개요: 기본 데이터베이스 서버에서 시스템 사용량이나 초당 트랜잭션(TPS)이 높은 경우 마이그레이션이 문제를 일으키고 있을 수 있습니다.
Prometheus 메트릭
각 배치된 백그라운드 마이그레이션에 대한 메트릭이 Prometheus에 게시됩니다. 이러한 메트릭은 Grafana에서 검색 및 시각화할 수 있습니다 (예제 보기).
열 교환 (릴리즈 N + 1)
백그라운드 마이그레이션이 완료되고 모든 레코드에 대해 새로운 bigint
열이 채워진 후, 우리는 열을 교환할 수 있습니다. 교환은 배포 후 마이그레이션을 통해 수행됩니다. 정확한 프로세스는 변환되는 테이블에 따라 다르지만 일반적으로 다음 단계를 따릅니다:
-
제공된
ensure_batched_background_migration_is_finished
헬퍼를 사용하여 배치 마이그레이션이 완료되었는지 확인하세요. (예제 보기). 마이그레이션이 완료되지 않았다면 이후 단계가 실패합니다. 미리 확인함으로써 더 유용한 오류 메시지를 제공할 수 있습니다. -
Gitlab::Database::MigrationHelpers::ConvertToBigint
모듈의add_bigint_column_indexes
헬퍼 메서드를 사용하여 기존 정수 열과 일치하는bigint
열에 인덱스를 생성합니다.- 헬퍼 메서드는 필요한 모든
bigint
인덱스를 생성할 것으로 예상되지만, 기존 인덱스가 누락되지 않도록 재확인하는 것이 좋습니다. 헬퍼에 대한 더 많은 정보는 병합 요청 135781에서 찾을 수 있습니다.
- 헬퍼 메서드는 필요한 모든
-
기존 정수 열과 일치하는
bigint
열을 사용하여 외래 키(FK)를 생성합니다. 이는 다른 테이블을 참조하는 FK와 마이그레이션 중인 테이블을 참조하는 FK 모두에 대해 수행합니다. (예제 보기). -
트랜잭션 내에서 열을 교환합니다:
-
관련 테이블을 잠급니다. 교착 상태에 걸릴 가능성을 줄이기 위해, 부모에서 자식으로 진행하는 것이 좋습니다. (예제 보기).
-
열 이름을 바꾸어 교환합니다. (예제 보기)
-
트리거 함수를 재설정합니다. (예제 보기).
-
기본값을 교환합니다. (예제 보기).
-
기본 키 제약 조건을 교환합니다 (있는 경우). (예제 보기).
-
이전 인덱스를 제거하고 새 인덱스의 이름을 변경합니다. (예제 보기).
-
add_bigint_column_indexes
헬퍼를 사용하여 생성된bigint
인덱스의 이름은Gitlab::Database::MigrationHelpers::ConvertToBigint
모듈의bigint_index_name
을 호출하여 가져올 수 있습니다.
-
-
이전 외래 키(여전히 존재하는 경우)를 제거하고 새 외래 키의 이름을 변경합니다. (예제 보기).
-
트리거 및 이전 integer
열 제거 (릴리스 N + 2)
배포 후 마이그레이션 및 제공된 cleanup_conversion_of_integer_to_bigint
도우미를 사용하여, 데이터베이스 트리거 및 이전 integer
열을 제거합니다 (예시 보기).
무시 규칙 제거 (릴리스 N + 3)
열이 제거된 후의 다음 릴리스에서, 더 이상 필요하지 않으므로 무시 규칙을 제거합니다 (예시 보기).
데이터 마이그레이션
데이터 마이그레이션은 까다로울 수 있습니다. 일반적인 데이터 마이그레이션 접근 방식은 3단계로 나누는 것입니다:
- 초기 데이터 배치를 마이그레이션합니다.
- 애플리케이션 코드를 배포합니다.
- 나머지 데이터를 마이그레이션합니다.
보통 이 방법이 효과적이지만, 항상 그렇지는 않습니다. 예를 들어, 필드의 형식을 JSON에서 다른 형식으로 변경해야 하는 경우 약간의 문제가 발생합니다. 애플리케이션 코드를 배포하기 전에 기존 데이터를 변경하면 오류가 발생할 가능성이 높습니다. 반면에 애플리케이션 코드를 배포한 후에 마이그레이션을 수행하면 같은 문제가 발생할 수 있습니다.
단순히 유효하지 않은 데이터를 수정해야 하는 경우, 배포 후 마이그레이션으로 충분합니다. 데이터 형식(예: JSON에서 다른 형식으로)을 변경해야 하는 경우, 새로운 데이터 형식에 대해 새로운 열을 추가하고 애플리케이션이 이를 사용하도록 하는 것이 일반적으로 가장 좋습니다. 이 경우 프로세스는 다음과 같습니다:
- 새로운 형식의 새 열을 추가합니다.
- 기존 데이터를 이 새 열로 복사합니다.
- 애플리케이션 코드를 배포합니다.
- 배포 후 마이그레이션에서 나머지 데이터를 복사합니다.
일반적으로 모든 경우에 맞는 해결책은 없으므로, 이러한 유형의 마이그레이션에 대해서는 머지 요청에서 논의하여 가능한 최상의 방법으로 구현되도록 하는 것이 가장 좋습니다.