CI 데이터베이스에 새로운 테이블 추가하기

파이프라인 데이터 파티셔닝 디자인 청사진에서는 CI 도메인의 기존 테이블을 파티션으로 나누는 방법을 설명합니다. 그러나 여전히 새로운 기능을 위한 테이블을 추가해야 합니다. 때로는 이러한 테이블에는 파티션을 분할해야 하는 대규모 테이블에 대한 참조가 있습니다. 미래의 작업을 줄이기 위해 파티셔너블 테이블에 속하는 모든 테이블은 시작부터 파티셔닝되어야 합니다.

새로운 라우팅 테이블 만들기

다음은 데이터베이스 헬퍼를 사용하여 새로운 테이블과 외래 키를 생성하는 예시입니다:

  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

파티션 관리하기

모델은 PARTITIONABLE_MODELS 디렉터리에 포함되어 있어야 합니다. 이는 partition_id가 올바르게 전파되었는지 테스트하는 데 사용되기 때문입니다.

이 디렉터리에 없는 경우, partitioned: true를 지정하면 첫 번째 파티션을 만듭니다. 또한 모델은 postgres_partitioning.rb 초기화 파일에 등록되어야 합니다.