2026년 4월 7일 작성
Debezium Snapshot Process - 초기 Data Capture 과정
Debezium snapshot은 global read lock 획득, binlog position 기록, schema capture, `REPEATABLE READ` transaction 내 data 읽기, lock 해제, streaming 전환의 순서로 진행되며, snapshot 도중 발생한 변경 사항은 streaming 단계에서 자동으로 처리됩니다.
Snapshot Process 개요
- Debezium의 snapshot process는 source database의 현재 상태를 일관성 있게 capture하여 target system으로 전송하는 일련의 단계입니다.
- connector가 처음 시작되거나 offset이 유실된 경우에 실행됩니다.
- snapshot이 완료된 후 streaming 단계로 자동 전환되어 실시간 변경 사항을 capture합니다.
- snapshot은 schema capture와 data capture의 두 가지 주요 작업으로 구성됩니다.
- schema capture : table 구조, column 정보, index 등 metadata를 수집합니다.
- data capture : table의 모든 record를 읽어 create event로 변환하여 전송합니다.
flowchart TD
start([Snapshot 시작])
lock[1. Global Read Lock 획득]
log_pos[2. Log Position 기록]
schema[3. Schema Capture]
tx[4. REPEATABLE READ Transaction 시작]
unlock[5. Global Read Lock 해제]
data[6. Data Capture]
commit[7. Transaction Commit]
save[8. Offset 저장]
stream[9. Streaming 전환]
done([Snapshot 종료])
start --> lock
lock --> log_pos
log_pos --> schema
schema --> tx
tx --> unlock
unlock --> data
data --> commit
commit --> save
save --> stream
stream --> done
Snapshot 단계별 상세 과정
- snapshot은 lock 획득부터 streaming 전환까지 순차적으로 진행됩니다.
1. Global Read Lock 획득
- snapshot의 첫 단계에서 global read lock을 획득하여 database 전체의 DDL 변경을 차단합니다.
- MySQL에서는
FLUSH TABLES WITH READ LOCK명령을 실행합니다. - 모든 table의 cache를 disk에 기록하고 read lock을 설정합니다.
- MySQL에서는
- global read lock이 유지되는 동안 어떤 session도 table 구조를 변경하거나 data를 쓸 수 없습니다.
snapshot.locking.mode가minimal인 경우, schema capture와 log position 기록이 끝나면 즉시 해제됩니다.
2. Log Position 기록
- 현재 시점의 transaction log 위치를 기록합니다.
- MySQL : binlog file 이름과 position, 또는 GTID를 기록합니다.
- PostgreSQL : LSN(Log Sequence Number)을 기록합니다.
- 기록된 log position은 streaming 시작점이자 connector 재시작 시 복구 기준이 됩니다.
- snapshot 완료 후 이 위치부터 streaming 단계가 시작됩니다.
- connector offset으로 저장되어 재시작 시 참조됩니다.
3. Schema Capture
- database의 metadata를 수집하여 table 구조 정보를 저장합니다.
- capture 대상 database와 table 목록을 조회합니다.
- 각 table의 column 이름, data type, nullable 여부, primary key 정보를 수집합니다.
- 수집된 schema 정보는 schema history topic(Kafka topic)에 저장됩니다.
- schema history는 이후 streaming 단계에서 DDL 변경을 추적하는 기준이 됩니다.
4. REPEATABLE READ Transaction 시작
REPEATABLE READisolation level의 transaction을 시작합니다.- MySQL InnoDB에서는
START TRANSACTION WITH CONSISTENT SNAPSHOT명령을 실행합니다. - transaction 시작 시점의 data 상태가 고정되어, 이후 다른 session의 변경 사항이 보이지 않습니다.
- MySQL InnoDB에서는
- MVCC(Multi-Version Concurrency Control)를 통해 lock 없이도 일관된 data 읽기가 가능합니다.
5. Global Read Lock 해제
- schema capture가 완료되고
REPEATABLE READtransaction이 시작된 후 global read lock을 즉시 해제합니다.snapshot.locking.mode가minimal인 경우에만 이 시점에서 해제됩니다.extendedmode에서는 snapshot 전체가 완료될 때까지 lock이 유지됩니다.
- lock이 해제된 이후에도
REPEATABLE READtransaction이 data 일관성을 유지합니다.
6. Data Capture
- table의 모든 record를 읽어 Debezium event로 변환하여 Kafka topic으로 전송합니다.
- 각 record는
opfield가r(read)인 create event로 변환됩니다. - event의
source.snapshotfield가true로 설정되어 snapshot event임을 식별 가능합니다.
- 각 record는
- data는 batch 단위로 처리됩니다.
snapshot.fetch.size설정으로 한 번에 읽어 들이는 record 수를 조절합니다.- 기본값은 2000이며, memory 상황에 따라 조정합니다.
- 대용량 table의 경우 chunk 단위 처리가 가능합니다.
- primary key 기준으로 table을 분할하여 순차적으로 처리합니다.
- memory 부하를 분산시키고 안정적인 처리를 보장합니다.
7. Transaction Commit 및 Offset 저장
-
모든 table의 data capture가 완료되면 transaction을 commit합니다.
-
2단계에서 기록한 log position을 offset으로 저장합니다.
- offset은 Kafka Connect의 offset storage에 저장됩니다.
- 저장된 offset은 streaming 단계의 시작점이자 connector 재시작 시 참조 정보입니다.
Snapshot에서 Streaming으로의 전환
- snapshot이 완료되면 connector는 자동으로 streaming 단계로 전환됩니다.
- streaming은 snapshot 시 기록한 log position부터 시작합니다.
- snapshot 진행 중에 발생한 변경 사항은 streaming 단계에서 순차적으로 처리됩니다.
flowchart LR
snapshot[Snapshot 완료]
log_pos[기록된 Log Position]
streaming[Streaming 시작]
realtime[실시간 변경 Capture]
snapshot --> log_pos
log_pos --> streaming
streaming --> realtime
- snapshot과 streaming 사이에 data 공백이 발생하지 않습니다.
- snapshot 시 기록한 log position 이후의 모든 변경 사항이 streaming에서 capture됩니다.
- 중복 event가 발생할 수 있으며, consumer 측에서 멱등성 처리가 필요합니다.
Snapshot 실패와 재시도
- snapshot 도중 오류가 발생하면 connector는 실패 상태가 됩니다.
- network 단절, database 연결 끊김, memory 부족 등이 원인입니다.
- connector를 재시작하면 snapshot을 처음부터 다시 수행합니다.
- 부분적으로 완료된 snapshot은 이어서 수행되지 않습니다.
- 이미 Kafka topic에 전송된 event는 중복으로 재전송됩니다.
- snapshot 실패를 방지하기 위한 사전 점검이 중요합니다.
- database connection timeout을 충분히 설정합니다.
- JVM heap size를 대상 table 크기에 맞게 설정합니다.
snapshot.fetch.size를 memory 상황에 맞게 조정합니다.
Reference
- https://debezium.io/documentation/reference/stable/connectors/mysql.html#mysql-snapshots
- https://debezium.io/documentation/reference/stable/connectors/postgresql.html#postgresql-snapshots