Skip to content

Fix race condition in sharded hashed dictionary parallel loading#96953

Merged
alexey-milovidov merged 2 commits intomasterfrom
fix-sharded-hashed-dict-race-condition
Feb 15, 2026
Merged

Fix race condition in sharded hashed dictionary parallel loading#96953
alexey-milovidov merged 2 commits intomasterfrom
fix-sharded-hashed-dict-race-condition

Conversation

@alexey-milovidov
Copy link
Member

Summary

  • Fix a TOCTOU race condition in the sharded hashed dictionary parallel loader that could cause occasional data loss during loading
  • The worker thread's tryPop could time out on an empty queue, then between checking isFinished(), the main thread could push the last block and call finish() — causing the worker to exit with unprocessed blocks still in the queue
  • Replace isFinished() with isFinishedAndEmpty() to atomically verify both that the queue is finished AND empty before the worker exits

Closes #84468

Changelog category (leave one):

  • Bug Fix (user-visible misbehavior in an official stable release)

Changelog entry (a user-readable short description of the changes that goes into CHANGELOG.md):

Fix a race condition in sharded HASHED dictionary parallel loading that could occasionally cause some rows to not be loaded.

🤖 Generated with Claude Code

alexey-milovidov and others added 2 commits February 15, 2026 03:10
…em.session_log`

The `DELETE FROM system.session_log` cleanup at the start of test
`02835_drop_user_during_session` creates a synchronous lightweight delete
mutation. In ASan stress tests, `system.session_log` receives continuous
writes from all concurrent test sessions, causing the mutation to take
over 12 minutes. Even though the query gets cancelled (`is_cancelled: 1`),
it remains stuck in `StorageMergeTree::waitForMutation`.

Fix by making the cleanup DELETE non-blocking with
`lightweight_deletes_sync = 0`. This is safe because the test user name
includes the PID (`$$`), making collisions from PID reuse extremely
unlikely during a single stress test run.

https://s3.amazonaws.com/clickhouse-test-reports/json.html?PR=96926&sha=724c57e90613f66e2ef897f80a644ba21e98b470&name_0=PR&name_1=Stress%20test%20%28arm_asan%2C%20s3%29

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a TOCTOU race in the worker thread loop: after `tryPop`
timed out (confirming the queue was empty), a context switch could
allow the main thread to push the final block and call `finish()`
before the worker checked `isFinished()`. The worker would then see
the queue as finished and exit, leaving the last block unprocessed.

This caused occasional loss of ~2000-3000 rows (one shard's portion
of the last source block) in sharded dictionaries loaded in parallel.

The fix replaces `isFinished()` with `isFinishedAndEmpty()`, which
atomically verifies both that the queue is marked finished AND that
no items remain. If items were pushed between the `tryPop` timeout
and this check, the worker correctly retries and processes them.

Closes #84468

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@clickhouse-gh
Copy link
Contributor

clickhouse-gh bot commented Feb 15, 2026

Workflow [PR], commit [552bbb7]

Summary:

@clickhouse-gh clickhouse-gh bot added the pr-bugfix Pull request with bugfix, not backported by default label Feb 15, 2026
@alexey-milovidov alexey-milovidov self-assigned this Feb 15, 2026
@alexey-milovidov
Copy link
Member Author

Amazing finding!

@alexey-milovidov alexey-milovidov merged commit e4d1f04 into master Feb 15, 2026
133 of 134 checks passed
@alexey-milovidov alexey-milovidov deleted the fix-sharded-hashed-dict-race-condition branch February 15, 2026 13:46
@robot-ch-test-poll4 robot-ch-test-poll4 added the pr-synced-to-cloud The PR is synced to the cloud repo label Feb 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr-bugfix Pull request with bugfix, not backported by default pr-synced-to-cloud The PR is synced to the cloud repo

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flaky 02730_dictionary_hashed_load_factor_element_count

2 participants