Change Data Capture (CDC) é o conjunto de técnicas para identificar e capturar mudanças (inserts, updates, deletes) em um banco de dados e propagá-las para outros sistemas. É a base de pipelines incrementais, sincronização de dados e arquiteturas event-driven.
Em vez de fazer full scan da tabela a cada execução, o CDC captura apenas o delta: o que mudou desde a última leitura.
Por que CDC
- Performance: ler só o que mudou é ordens de magnitude mais rápido que full scan
- Latência baixa: mudanças podem ser propagadas em segundos (streaming) ou minutos (micro-batch)
- Auditoria: histórico completo de todas as mudanças, na ordem em que ocorreram
- Desacoplamento: a fonte não precisa saber quem consome as mudanças
Abordagens de CDC
1. Timestamp / Coluna de controle (query-based)
Lê registros onde updated_at >= ultima_execucao. Simples, mas com limitações sérias.
-- Captura registros modificados desde a última leitura
SELECT * FROM pedidos
WHERE updated_at >= '2026-05-01 00:00:00';Limitações:
- Não captura DELETEs (registro some da tabela)
- Depende de colunas
updated_atexistentes e atualizadas corretamente - Sujeito a race conditions (registro modificado exatamente no momento da query)
- Não garante ordem dos eventos
Quando usar: tabelas pequenas, casos simples, sem necessidade de capturar deletes.
2. Log-based CDC (recomendado)
Lê o transaction log / WAL (Write-Ahead Log) do banco de dados diretamente. Captura todos os eventos (insert, update, delete) na ordem exata em que ocorreram, sem impactar a performance do banco.
PostgreSQL WAL → Debezium → Kafka → consumidores
MySQL binlog → Debezium → Kafka → consumidores
SQL Server CDC → Debezium → Kafka → consumidores
Vantagens:
- Captura DELETEs
- Baixa latência (sub-segundo possível)
- Zero impacto na fonte (leitura do log, não das tabelas)
- Ordem garantida dos eventos
Ferramentas principais: Debezium, AWS DMS, Google Datastream, Fivetran, Airbyte.
3. Trigger-based CDC
Triggers no banco de dados escrevem mudanças em uma tabela de log.
CREATE TRIGGER trg_pedidos_cdc
AFTER INSERT OR UPDATE OR DELETE ON pedidos
FOR EACH ROW
INSERT INTO pedidos_cdc_log (operacao, dados, timestamp) VALUES (...);Desvantagens: impacto direto na performance da fonte, complexidade de manutenção. Evitar em produção com alto volume.
Debezium
Principal ferramenta open-source para log-based CDC. Conecta ao log do banco e publica eventos no Kafka.
// Exemplo de evento Debezium no Kafka
{
"op": "u",
"before": { "pedido_id": 1, "status": "pendente" },
"after": { "pedido_id": 1, "status": "processado" },
"source": { "table": "pedidos", "ts_ms": 1746057600000 }
}Operações: c (create/insert), u (update), d (delete), r (read/snapshot).
CDC no ecossistema de dados
flowchart LR DB[(Banco\nrelacional)] -->|log-based CDC| D[Debezium] D -->|eventos| K[Kafka] K -->|streaming| S[Spark Structured\nStreaming] K -->|streaming| F[Flink] S --> L[(Lakehouse\nDelta / Iceberg)] L -->|SCD aplicado| DW[(Data Warehouse)]
CDC como fonte para SCD
CDC fornece os eventos brutos; SCD define como esses eventos são materializados na dimensão:
| Evento CDC | SCD Tipo 1 | SCD Tipo 2 |
|---|---|---|
| INSERT | Insert | Insert (versão 1) |
| UPDATE | Update | Fecha versão atual + nova linha |
| DELETE | Delete / soft delete | Fecha versão atual |
CDC no Databricks
No Databricks, Change Data Feed (CDF) é o equivalente interno do CDC para tabelas Delta: captura mudanças entre versões de uma tabela Delta e as expõe como stream de eventos.
Para ingestão de fontes externas, o Databricks suporta Auto Loader com Kafka (Debezium) ou serviços como Fivetran/Airbyte que entregam os dados na Bronze.
# Consumir CDC do Kafka (eventos Debezium) com Spark Streaming
from pyspark.sql import functions as F
kafka_df = (
spark.readStream
.format("kafka")
.option("kafka.bootstrap.servers", "broker:9092")
.option("subscribe", "db.public.pedidos")
.load()
)
parsed_df = kafka_df.select(
F.from_json(F.col("value").cast("string"), schema).alias("data")
).select("data.*")
# Aplicar upsert na tabela Delta (SCD Tipo 1)
def upsert_delta(batch_df, batch_id):
from delta.tables import DeltaTable
delta = DeltaTable.forName(spark, "silver.pedidos")
delta.alias("alvo").merge(
batch_df.filter("op != 'd'").alias("origem"),
"alvo.pedido_id = origem.after.pedido_id"
).whenMatchedUpdateAll().whenNotMatchedInsertAll().execute()
parsed_df.writeStream.foreachBatch(upsert_delta).start()Considerações de produção
- Exactly-once vs at-least-once: a maioria dos sistemas CDC garante at-least-once. Idempotência no consumidor é necessária.
- Schema evolution: se o schema da fonte mudar, o CDC precisa lidar com isso. Debezium + Avro + Schema Registry é o padrão.
- Snapshot inicial: antes de capturar apenas o delta, é preciso fazer um snapshot completo da tabela. Debezium faz isso automaticamente.
- Lag monitoring: monitorar o atraso entre evento na fonte e chegada no destino é crítico em pipelines near-realtime.
Ver também: pipeline-de-dados | scd-slowly-changing-dimensions | databricks-cdf | databricks-delta-lake | arquitetura-medalhao | engenharia-de-dados