CI 거울 테이블
문제 설명
GitLab이 사용하는 단일 데이터베이스를 두 개의 데이터베이스(main 및 ci)로 분할하는 작업 분해 작업의 일부로, 다른 데이터베이스에 속하는 테이블 간 조인을 모두 제거하는 일이 있었습니다. PostgreSQL은 서로 다른 데이터베이스에 속하는 테이블 간의 조인을 지원하지 않기 때문입니다. 그러나 main 데이터베이스의 일부 중요한 응용 프로그램 모델은 CI 쪽에서 매우 자주 쿼리됩니다. 예를 들면:
-
namespaces
테이블의Namespace
-
projects
테이블의Project
이러한 테이블에서 조인을 할 수 없는 것은 큰 도전입니다. 팀은 이러한 테이블을 main 데이터베이스에서 CI 데이터베이스로 논리적으로 복제하기로 결정했고, 이를 새로운 테이블에 반영했습니다.
-
namespaces
테이블의 거울인ci_namespace_mirrors
-
projects
테이블의 거울인ci_project_mirrors
이 논리적 복제는 두 가지를 의미합니다:
-
main
데이터베이스 테이블은namespaces
및projects
테이블에 조인하여 쿼리 가능합니다. -
ci
데이터베이스 테이블은ci_namespace_mirrors
및ci_project_mirrors
테이블과 조인할 수 있습니다.
이 복제는 각 모델에서 필요한 몇 가지 속성에만 제한되었습니다:
-
Namespace
에서는traversal_ids
를 복제합니다. -
Project
에서는 프로젝트가 속한 그룹을 나타내는namespace_id
만을 복제합니다.
소스 테이블과 대상 테이블의 동기화 유지
소스와 대상 테이블을 동기화 유지하기 위해 두 가지 유형의 3 이벤트에 유의해야 합니다:
- 새로운 namespaces 또는 projects를 만드는 경우.
- namespaces 또는 projects를 업데이트하는 경우.
- namespaces/projects를 삭제하는 경우.
만들고 업데이트하기
새롭게 생성되거나 업데이트된 namespaces 또는 projects의 데이터를 동기화하는 방법은 다음과 같습니다:
-
main 데이터베이스에서:
namespaces
또는projects
테이블에 대한 모든INSERT
또는UPDATE
는namespaces_sync_events
및projects_sync_events
테이블에 항목을 추가합니다. 이러한 테이블은 또한 main 데이터베이스에 있습니다. 이러한 항목은 두 테이블의 트리거에 의해 추가됩니다. -
모델 수준에서: 소스 모델
Namespace
또는Project
중 하나에 커밋이 발생한 후에 해당하는 Sidekiq 작업Namespaces::ProcessSyncEventsWorker
또는Projects::ProcessSyncEventsWorker
를 스케줄합니다. - 그런 다음, 이러한 워커는:
-
main
데이터베이스에서(namespaces/project)_sync_events
테이블에서 항목을 읽어 동기화할 namespaces 또는 projects를 확인합니다. - 업데이트된 레코드의 데이터를
ci_namespace_mirrors
,ci_project_mirrors
대상 테이블로 복사합니다.
-
삭제
namespaces
또는 projects
중 하나가 삭제되면, 미러 CI 테이블의 대상 레코드는 loose foreign keys (LFK) 메커니즘을 사용하여 삭제됩니다.
config/gitlab_loose_foreign_keys.yml
항목을 가지고 있기 때문에 LFK 메커니즘은 이미 의도한 대로 작동했습니다. 이 메커니즘은 main 데이터베이스에서 삭제된 namespaces
또는 projects
에 매핑된 미러 테이블의 레코드를 삭제했습니다.
ci_namespace_mirrors:
- table: namespaces
column: namespace_id
on_delete: async_delete
ci_project_mirrors:
- table: projects
column: project_id
on_delete: async_delete
일관성 확인
동기화 메커니즘이 의도한 대로 작동하는지 확인하려면 몇 분마다 크론 작업에 의해 트리거되는 추가적인 워커 작업 두 개를 배포합니다:
Database::CiNamespaceMirrorsConsistencyCheckWorker
Database::CiProjectMirrorsConsistencyCheckWorker
이러한 작업은 다음과 같습니다:
- 커서를 사용하여
main
데이터베이스의 소스 테이블 둘을 스캔합니다. -
ci
데이터베이스에서 대상 테이블과 namespaces 및 projects의 항목을 비교합니다. - 동기화되지 않은 항목을 Kibana 및 Prometheus에 보고합니다.
- 불일치를 수정합니다.