CI 데이터베이스에 새로운 테이블 추가하기
파이프라인 데이터 파티셔닝 설계 블루프린트는 CI 도메인의 기존 테이블을 파티셔닝하는 방법을 설명합니다. 그러나 새로운 기능을 위한 테이블을 추가해야 할 때도 있습니다. 때로는 이러한 테이블은 파티셔닝해야 할 대형 테이블을 참조합니다. 미래의 작업을 줄이기 위해 파티셔닝 가능한 테이블에 belongs_to
연관관계를 사용하는 모든 테이블은 처음부터 파티셔닝되어야 합니다.
새 라우팅 테이블 생성하기
다음은 새 테이블과 외래 키를 만드는 데이터베이스 도우미를 사용하는 예입니다.
include Gitlab::Database::PartitioningMigrationHelpers
disable_ddl_transaction!
def up
create_table(:p_ci_examples, primary_key: [:id, :partition_id], options: 'PARTITION BY LIST (partition_id)', if_not_exists: true) do |t|
t.bigserial :id, null: false
t.bigint :partition_id, null: false
t.bigint :build_id, null: false
end
add_concurrent_partitioned_foreign_key(
:p_ci_examples, :p_ci_builds,
column: [:partition_id, :build_id],
target_column: [:partition_id, :id],
on_update: :cascade,
on_delete: :cascade,
reverse_lock_order: true
)
end
def down
drop_table :p_ci_examples
end
이 테이블은 라우팅 테이블이라고 하며 어떤 데이터도 보관하지 않습니다. 데이터는 파티션에 저장됩니다.
라우팅 테이블을 생성할 때:
- 테이블 이름은
p_
접두사로 시작해야 합니다. 모든 쿼리가 라우팅 테이블을 통과하고 파티션에 직접 액세스하지 않도록 하는 분석기가 있습니다. - 각 새 테이블에는
partition_id
열이 필요하며 그 값은 관련 연관관계에서의 값과 같아야 합니다. 이 예에서는p_ci_builds
입니다. 파이프라인에 속하는 모든 리소스는 동일한partition_id
값을 공유합니다. - 기본 키는 효율적인
id
로의 검색만을 허용하기 위해 이 순서대로 열을 가져야 합니다. - 외래 키 제약 조건에는
ON UPDATE CASCADE
옵션이 포함되어야 합니다. 왜냐하면partition_id
값은 파티션을 재분배하기 위해 업데이트되어야 하기 때문입니다.
첫 번째 파티션 생성하기
보통 초기 파티션은 애플리케이션에 부팅 시 생성되도록 의존합니다. 그러나 CI 테이블의 고트래픽과 대량의 노드로 인해 참조 테이블에 잠금을 얻기가 어려울 수 있습니다. 결과적으로 배포 중에 노드가 시작에 실패할 수 있습니다. 이 실패를 방지하기 위해 애플리케이션이 실행되기 전에 파티션이 이미 존재하는지 보장해야 합니다.
disable_ddl_transaction!
def up
with_lock_retries do
connection.execute(<<~SQL)
LOCK TABLE p_ci_builds IN SHARE ROW EXCLUSIVE MODE;
LOCK TABLE ONLY p_ci_examples IN ACCESS EXCLUSIVE MODE;
SQL
connection.execute(<<~SQL)
CREATE TABLE IF NOT EXISTS gitlab_partitions_dynamic.ci_examples_100
PARTITION OF p_ci_examples
FOR VALUES IN (100);
SQL
end
end
파티션은 gitlab_partitions_dynamic
스키마에 생성됩니다.
파티션을 생성할 때 다음을 기억하세요:
- 파티션 이름에
p_
접두사를 사용하지 않습니다. -
partition_id
의 시작 값은100
입니다.
파티션 값 연쇄화하기
파티션 값을 연쇄하기 위해 모듈은 Ci::Partitionable
모듈을 사용해야 합니다.
class Ci::Example < Ci::ApplicationRecord
include Ci::Partitionable
self.table_name = :p_ci_examples
self.primary_key = :id
belongs_to :build, class_name: 'Ci::Build'
partitionable scope: :build, partitioned: true
end
파티션 관리하기
이 모델은 partition_id
가 올바르게 전파되었는지 테스트하는 데 사용되므로 PARTITIONABLE_MODELS
목록에 포함되어야 합니다.
누락된 경우 partitioned: true
를 지정하면 처음 파티션이 생성됩니다. 또한 모델은 postgres_partitioning.rb
이니셜라이저에 등록되어야 합니다.