Oracle CDC — Quickstart & Runbook

Confirm prerequisites, collect health signals, register a connector, verify changes, and roll back safely.

Prerequisites (DB)

  • ARCHIVELOG mode recommended.
  • Supplemental logging enabled (DB-level minimal; table-level for key columns or ALL for keyless tables).
  • Redo/archive retention window ≥ snapshot + catch-up time.
  • Stable primary keys (or table log groups capturing merge keys).
  • ARCHIVELOG mode keeps redo history available so CDC readers can recover. Supplemental logging ensures redo contains key columns to reconstruct before/after images, which is critical when applying updates downstream.
-- archivelog and redo
SELECT log_mode FROM v$database;
SELECT sequence#, archived, status
FROM v$log
ORDER BY first_time DESC FETCH FIRST 5 ROWS ONLY;

-- supplemental logging
SELECT supplemental_log_data_min, supplemental_log_data_all FROM v$database;
SELECT owner, table_name, log_group_name, always, log_group_type
FROM dba_log_groups ORDER BY owner, table_name;

DB Setup (examples)

-- table-level log group for keyless merge
ALTER TABLE APP.CUSTOMER ADD LOG GROUP lg_customer_pk (ID) ALWAYS;

-- throttle snapshot scope to avoid redo storms (choose limited tables)
-- and plan off-hours if tables are huge

Connector Notes

  • Prefer narrow includes/filters to reduce LogMiner workload.
  • Measure redo switch rate before and after snapshot.
  • Have a plan for LOBs (exclude or route separately if large).
{
  "name": "oracle-cdc",
  "config": {
    "connector.class": "io.debezium.connector.oracle.OracleConnector",
    "database.hostname": "oracle",
    "database.port": "1521",
    "database.user": "CDC",
    "database.password": "CDC",
    "database.dbname": "ORCLCDB",
    "database.pdb.name": "ORCLPDB1",
    "topic.prefix": "server1",
    "schema.include.list": "APP",
    "table.include.list": "APP.CUSTOMER",
    "tombstones.on.delete": "false",
    "include.schema.changes": "false",
    "snapshot.mode": "initial",
    "errors.tolerance": "all",
    "errors.deadletterqueue.topic.name": "dlq.oracle"
  }
}

Verify

-- generate a change
UPDATE APP.CUSTOMER SET EMAIL = EMAIL || '.X' WHERE ROWNUM = 1;

-- redo activity sample
SELECT TO_CHAR(first_time, 'YYYY-MM-DD HH24:MI') AS t, COUNT(*) AS switches
FROM v$log_history
WHERE first_time > SYSDATE - 1/24
GROUP BY TO_CHAR(first_time, 'YYYY-MM-DD HH24:MI');
kafka-console-consumer --bootstrap-server localhost:9092 \
  --topic server1.APP.CUSTOMER --from-beginning --max-messages 5

Acceptance (target/sink)

  • No duplicate PKs after connector restart.
  • Latest-wins per key by commit timestamp/SCN.
  • DLQ empty or only expected test errors.
SELECT COUNT(*) AS rows, COUNT(DISTINCT ID) AS distinct_keys
FROM TARGET_CUSTOMERS;

Safe Rollback

Pause the connector and retain archived logs until downstream systems are consistent. If schema or log-group changes are needed, plan a clean re-snapshot of affected tables.