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_at existentes 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 CDCSCD Tipo 1SCD Tipo 2
INSERTInsertInsert (versão 1)
UPDATEUpdateFecha versão atual + nova linha
DELETEDelete / soft deleteFecha 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