You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(cutover): frame cross-replica ON CLUSTER skew for multi-replica production + maintenance note
The prior comment-precision pass described the cross-host ON CLUSTER case as "a non-issue in
the default single-node deployment", which downplays it: production is multi-replica. Correct
the framing in the stage-B/C rollback SQL, finalize.sh and the runbook, and add the operator
maintenance note.
- Cross-replica: ON CLUSTER runs synchronously (the client blocks until every reachable replica
applies it, or throws naming a laggard that then converges via the DDL queue), so there is no
durable mixed topology — only a sub-second cross-replica skew as it propagates, the same
accepted skew as the wrap. Not globally atomic (no ClickHouse primitive for that); nil on a
single replica.
- Rollback stages B/C rename the LIVE `traces`, so reads hit the skew: rollback.sh now prints a
maintenance NOTE and the runbook says to run the rollback in a maintenance moment / with reads
quiesced on a multi-replica cluster.
- finalize is EXEMPT: its TRUNCATE+RENAME touch only the parked backup / disposable shadow, never
the live `traces`, so there is no live-read skew and no maintenance window is needed — stated
explicitly in finalize.sh and the runbook.
Comment/doc-only; no behavior change.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: apps/opik-backend/data-migrations/traces-local-v2-cutover/scripts/db-app-analytics/000004_rollback_stage_b_exchange_back.sql
+6-4Lines changed: 6 additions & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -8,10 +8,12 @@
8
8
-- restoring the canonical state: traces = original live, traces_post_rollback_backup = successor parked. Gapless and with
9
9
-- no orphan risk: the multi-target RENAME is one statement, atomic PER HOST (all clauses apply or none), so on any node
10
10
-- there is no window where a partial failure strands the successor under a wrong name — the flaw of a separate
11
-
-- EXCHANGE + RENAME, which has that window even on a single host. ACROSS hosts, ON CLUSTER is serialized through the DDL
12
-
-- queue and eventually-consistent, NOT globally atomic: a briefly lagging host converges on its own (or the ON CLUSTER
13
-
-- call fails loudly naming it) — the same accepted skew as any ON CLUSTER DDL, and a non-issue in the default single-node
14
-
-- deployment (one host). Non-destructive.
11
+
-- EXCHANGE + RENAME, which has that window even on a single host. ACROSS the shard's replicas (production is multi-replica)
12
+
-- ON CLUSTER runs synchronously — the client blocks until every reachable replica applies it, or throws naming a laggard
13
+
-- that then converges via the DDL queue — so there is no durable mixed topology, only a sub-second cross-replica skew as
14
+
-- it propagates, during which a read on a not-yet-renamed replica sees the old `traces`. That is the same accepted
15
+
-- ON CLUSTER skew as the wrap (nil on a single replica); run this in the rollback maintenance moment (see the runbook).
16
+
-- Non-destructive.
15
17
-- rollback.sh runs the reverse-replay (000004_rollback_reverse_replay.sql) right after this so deletes since
16
18
-- cutover_start do not resurrect. rollback.sh asserts the post-EXCHANGE, pre-wrap topology (traces = successor schema,
Copy file name to clipboardExpand all lines: apps/opik-backend/data-migrations/traces-local-v2-cutover/scripts/db-app-analytics/000004_rollback_stage_c_promote_original.sql
+5-3Lines changed: 5 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -8,9 +8,11 @@
8
8
-- `traces` (the name freed by the first clause), and the successor shard (`traces_local`) parks as
9
9
-- `traces_post_rollback_backup` (a retained backup, dropped only by finalize.sh — NOT the disposable `traces_local_v2`
10
10
-- shadow) — ending in the canonical state (traces = original live, traces_post_rollback_backup = successor parked). So
11
-
-- `traces` is never absent on a node. ACROSS hosts, as for any ON CLUSTER DDL, the rename is eventually-consistent (a
12
-
-- lagging host converges on its own, or the call fails loudly naming it), NOT globally atomic — a non-issue in the
13
-
-- default single-node deployment (one host).
11
+
-- `traces` is never absent on a node. ACROSS the shard's replicas (production is multi-replica) ON CLUSTER runs
12
+
-- synchronously — the client blocks until every reachable replica applies it, or throws naming a laggard that then
13
+
-- converges via the DDL queue — NOT globally atomic, so the only exposure is a sub-second cross-replica skew as it
14
+
-- propagates, during which a read on a not-yet-renamed replica sees the pre-rollback `traces` (the same accepted
15
+
-- ON CLUSTER skew as the wrap; nil on a single replica). Run this in the rollback maintenance moment (see the runbook).
14
16
--
15
17
-- Then drop the ex-wrapper. It is dropped under `traces_dist_old` — a fresh name that ONLY the data-less wrapper ever
16
18
-- occupied — so the DROP cannot hit the original data regardless of per-replica DDL timing (the concern with dropping a
0 commit comments