8000 fix(python): re-check a differing table before reporting a checksum difference (Spec 13.06 section 3.7.3) by minguyen9988 · Pull Request #1547 · Altinity/clickhouse-sink-connector · GitHub
[go: up one dir, main page]

Skip to content

fix(python): re-check a differing table before reporting a checksum difference (Spec 13.06 section 3.7.3) - #1547

Merged
minguyen9988 merged 1 commit into
2.11.0from
fix-checksum-recheck-differences
Oct 2, 2026
Merged

minguyen9988 merged 1 commit into
2.11.0from
fix-checksum-recheck-differences

Conversation

@minguyen9988
@minguyen9988 minguyen9988 commented Oct 2, 2026 •
Copy link
Copy Markdown
Collaborator

Problem: on a table that is written during a checksum run, the sides read it at different moments, and the MySQL side reads its PK chunks over separate connections, each with its own snapshot. One pass can therefore report a difference although no row diverges. Observed on a scheduled run on 2026-10-01: the ClickHouse side finished at 17:45:30; 15 rows were closed (db_to set) at 17:45:35.9 and their 15 successors inserted from 17:45:36.7 to 17:45:38.4, while the MySQL side ran from 17:45:28 to 17:46:04 in 16 PK chunks. The chunk holding the closed rows saw the update and the last chunk did not see the inserts, so both sides reported 27,368,866 rows with different md5s. The next run matched, and the 30 rows hold identical values on both sides.

Change (both drivers, legacy and packaged):

  • Each table runs through verify_table. A DIFFERENT pass is checksummed again --recheck_differences more times (default 1), --recheck_delay_seconds apart (default 60), so the connector can apply the writes the pass raced with.
  • Earlier passes log the mismatch at INFO (Checksum mismatch on pass k of n, ...). Only the last pass logs the WARNING Checksum difference line that scheduled jobs fail on: a difference that persists still fails the job, one the re-check no longer sees does not.
  • A re-check that ends in ERROR is an ERROR. A MATCH after a re-check is a real match (every side hashed the whole filtered table to the same md5 and count in that pass).
  • --recheck_differences 0 restores the single pass. A caller that builds its own argparse.Namespace without the new attributes keeps the single pass (recheck_settings uses getattr).
  • The WARNING is now logged from the table's worker thread instead of MainThread; its message text is unchanged.

Spec: 13.06 gains section 3.7.3, two CLI rows, the outcome-table row, the DIFFERENT logging rule in 3.8 and the new tests in 5.1. D-13.06-36 (replica catch-up is never established) stays open and is marked mitigated, not fixed: a table written so continuously that every pass races a write can still be reported DIFFERENT. Fixing that needs a source binlog position read in the same snapshot and a wait for the connector offset to pass it.

Verification:

  • New sink-connector/python/db_compare/tests/test_checksum_recheck.py: the legacy driver end to end with the scheduled job's command line against a stand-in side whose output changes between passes (difference gone on re-check, difference seen again, --recheck_differences 0, delay and count honoured), plus verify_table in both copies (match, persistent difference, error on re-check, no re-check on a first-pass match, argument validation).
  • python -m pytest db_compare/tests db_dump db_load: 649 passed, 4 skipped. The 2.11.0 baseline for db_compare/tests alone is 240 passed, 1 skipped; every pre-existing test still passes.
  • Mutation (re-check removed in both copies): 7 of the new tests fail.
  • scripts/validate_specs.py --changed-base origin/2.11.0: Validation PASSED (83 specs, 1194 verification citations).

🤖 Generated with Claude Code

…ifference (Spec 13.06 section 3.7.3)

On a table written during the run the sides read it at different moments, and the MySQL side reads its PK chunks over separate connections, so one pass can differ although no row diverges. Seen on a scheduled run: 15 rows closed and 15 successors inserted mid-scan gave equal counts (27,368,866) and different md5s; the next run matched and the 30 rows are identical on both sides.

Both drivers now run each table through verify_table: a DIFFERENT pass is checksummed again --recheck_differences more times (default 1), --recheck_delay_seconds apart (default 60). Earlier passes log the mismatch at INFO; only the last pass logs the WARNING 'Checksum difference' that scheduled jobs fail on, so a difference that persists still fails the job and one the re-check no longer sees does not. A re-check that errors is an ERROR. --recheck_differences 0 restores the single pass, and a caller that builds its own Namespace without the new attributes keeps it. D-13.06-36 (catch-up not established) stays open; this mitigates its noise.

Tests: new db_compare/tests/test_checksum_recheck.py (legacy driver end to end with the scheduled job's flags; verify_table in both copies). db_compare, db_dump and db_load: 649 passed, 4 skipped. Mutation (re-check removed): 7 of the new tests fail.

Co-Authored-By: Claude Opus 5.5 (1M context) [noreply@anthropic.com]
@minguyen9988
minguyen9988 merged commit ac591ce into 2.11.0 Oct 2, 2026
13 checks passed
@minguyen9988
minguyen9988 deleted the fix-checksum-recheck-differences branch October 2, 2026 04:47
minguyen9988 added a commit that referenced this pull request Oct 2, 2026
#1547 was squash-merged into 2.11.0 with the same content as its commit on this branch (40162c9), and #1537-#1543 were merged with no content change, so the two conflicting files keep this branch's version: 2.11.0's version of them plus this PR's change.

Co-Authored-By: Claude Opus 5.5 (1M context) [noreply@anthropic.com]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

0