MySQL CDC — Quickstart & Runbook

Configure binlog safely, register a connector, verify changes, and roll back cleanly.

Prerequisites (DB)

  • binlog_format=ROW with binlog_row_image FULL or MINIMAL per connector support.
  • GTID mode preferred (gtid_mode=ON).
  • Binlog retention window ≥ snapshot + catch-up time.
  • Stable primary keys (or sink logic that can reconcile keyless tables).
  • binlog_format=ROW captures per-row changes for high-fidelity CDC. binlog_row_image controls how much data is logged, and gtid_mode=ON simplifies failover by uniquely identifying each transaction across replicas.
SHOW VARIABLES LIKE 'binlog_format';
SHOW VARIABLES LIKE 'binlog_row_image';
SHOW VARIABLES LIKE 'gtid_mode';
SHOW MASTER STATUS;
SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';

DB Setup (copy/paste)

# my.cnf (server)
binlog_format = ROW
binlog_row_image = FULL
server_id = 1
gtid_mode = ON
enforce_gtid_consistency = ON

# grant minimal privileges to CDC user
GRANT REPLICATION SLAVE, REPLICATION CLIENT, SELECT ON *.*
  TO 'cdc'@'%' IDENTIFIED BY 'cdc';

Connector Config (example)

{
  "name": "mysql-cdc",
  "config": {
    "connector.class": "io.debezium.connector.mysql.MySqlConnector",
    "database.hostname": "mysql",
    "database.port": "3306",
    "database.user": "cdc",
    "database.password": "cdc",
    "database.server.id": "5400",
    "topic.prefix": "server1",
    "database.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.mysql"
  }
}

Verify

-- generate a change
UPDATE app.customer SET email = CONCAT(email, '.x')
WHERE id = (SELECT id FROM app.customer LIMIT 1);

-- confirm binlog advancing
SHOW MASTER STATUS;
-- topic should receive a record for app.customer
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 using op_ts/version.
SELECT COUNT(*) AS rows, COUNT(DISTINCT id) AS distinct_keys
FROM target_customers;

Safe Rollback

Stop the connector; keep binlogs until you are sure downstream systems are consistent. If you must prune logs, confirm all consumers are caught up first.