Skip to content

MySQL CDC to ClickHouse Final State Guide

June 2026

MySQL to ClickHouse can be fast and useful, but the final-state contract depends on both binlog ordering and ClickHouse merge behavior.

Short Answer

MySQL CDC to ClickHouse works by reading MySQL row-level binlog events and inserting versions of those rows into ClickHouse with ReplacingMergeTree semantics. Skippr adds a _skippr_order_token String column to each CDC-managed table, and ClickHouse keeps the version with the highest order token during merges. Deletes are handled separately with tombstone tracking and ALTER TABLE ... DELETE WHERE.

A practical example is inventory.sku 77 changing quantity from 18 to 11. MySQL emits an UPDATE_ROWS event with the full row image, and Skippr writes the newer version into ClickHouse with a newer order token. Query results may briefly show duplicate versions until a background merge runs, which is why the docs recommend FINAL when you need point-in-time consistency on fresh data.

Why Teams Struggle with This

The interesting part of this pipeline is that the source ordering is strict but the destination visibility can be delayed. MySQL gives you a durable binlog position, while ClickHouse reaches its deduplicated final state through background merges rather than immediate row replacement.

  • MySQL still needs ROW binlog format and FULL row images, or the pipeline starts with incomplete mutation data.
  • ClickHouse can show recent duplicate versions until ReplacingMergeTree merges have converged.
  • Delete correctness depends on tombstones plus ClickHouse delete processing, not just on dropping rows when a delete arrives.
  • Readers who need the latest answer immediately should query with FINAL as the docs recommend.

How Skippr Handles It

Skippr is useful here because it does not hide the warehouse trade-off. It stores the MySQL binlog filename and position for durable restarts, writes order tokens into ClickHouse, and creates the companion tombstone table automatically. The pipeline is honest about the fact that ClickHouse reaches final state through merge behavior rather than through immediate in-place updates.

That lets teams explain the gap between ingestion correctness and query-time visibility. A row can be correct in the CDC contract and still require FINAL for a fully converged answer right after a burst of updates.

  • MySQL row-event CDC with durable binlog-position resumes.
  • ClickHouse _skippr_order_token columns for version ordering.
  • ReplacingMergeTree-based upsert convergence on the highest token.
  • Tombstone tracking plus delete application for removed keys.

What the First Useful Version Looks Like

Use this integration when ClickHouse is the analytics engine and the team is comfortable with its merge model.

The important habit is teaching query consumers the difference between recently written versions and fully merged final state.