CI 데이터베이스에 새 테이블 추가

pipeline data partitioning 설계 문서는 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

파티션 관리

모델은 PARTITIONABLE_MODELS 목록에 포함되어야 하며, 이는 partition_id가 올바르게 전파되는지 테스트하는 데 사용됩니다.

누락된 경우, partitioned: true를 지정하면 첫 번째 파티션이 생성됩니다. 모델은 또한 postgres_partitioning.rb 초기화 파일에 등록되어야 합니다.