mutations_sync = 1 vs Asynchronous Mutations for Schema Consistency
0 reputation · 24 Jun 2021, 12:46 UTC
0 reputation · 24 Jun 2021, 12:46 UTC
When executing ALTER TABLE ... UPDATE or similar mutations on a ReplicatedMergeTree table across a cluster, ClickHouse manages these changes asynchronously by default. The metadata is propagated via ZooKeeper, but the actual data rewriting occurs in the background as parts are merged.
In environments requiring strict consistency, there is a trade-off between using the default asynchronous behavior and enabling SET mutations_sync = 1. While the synchronous setting ensures the client session blocks until the mutation is applied, it introduces significant latency and potential timeouts for large datasets.
The uncertainty lies in balancing write availability against the risk of a query hitting a replica where the mutation has not yet completed, leading to inconsistent results across the cluster.
mutations_sync = 1 guarantee that all replicas have physically applied the change before the command returns?33775 reputation · 24 Jun 2021, 15:15 UTC
1. Does mutations_sync = 1 guarantee that all replicas have physically applied the change before the command returns?
ALTER reports that its own mutation is finished. The mutation is still applied asynchronously on the other replicas.2. What are the performance implications for insert throughput when synchronous mutations are enforced on high‑volume tables?
mutations_sync = 0 (default), the ALTER command returns immediately after registering the mutation in ZooKeeper. Physical rewriting occurs in the background.mutations_sync = 1, the client session blocks until the executing replica reports is_done = 1 for that mutation. No cluster‑wide barrier is enforced.Because the mutation is applied per‑replica, a query that hits a different replica immediately after an ALTER with mutations_sync = 1 can still read the pre‑mutation data. Full consistency across the cluster requires waiting for all replicas to finish the mutation, which can be verified via system.mutations on each replica.
When the merge thread is busy finishing a mutation, the replica is temporarily less available for new inserts. The longer the mutation, the greater the contention. In high‑volume workloads, this can noticeably lower the number of rows inserted per second and increase write latency.
ALTER, query system.mutations on each replica to confirm is_done = 1 before performing a read that must see the mutation.ALTER or wait until system.mutations shows all replicas finished.merge_mutations and insert_rows metrics to assess the throughput impact when toggling mutations_sync.To tailor the recommendation further, could you let us know the typical size of the mutations you run (e.g., number of rows or part size) and the number of replicas per table?
Use comments to ask for clarification. Post a solution as an answer.
33,775 reputation · 24 Jun 2021, 18:03 UTC
To build on the previous point regarding mutations_sync = 1, it is important to distinguish between the coordinator replica and the follower replicas. Since the setting only blocks until the local replica finishes, it does not provide linearizable read-after-write consistency across the cluster.
If your application requires strict consistency before proceeding, you cannot rely on the ALTER return code alone. Instead, you should programmatically verify the mutation status across all nodes. This can be done by querying the system.mutations table on each replica:
SELECT replica, is_done FROM clusterAllReplicas('your_cluster', system.mutations) WHERE mutation_id = 'your_mutation_id';Only when
is_done = 1across all targeted replicas can you guarantee that subsequent queries will return consistent results regardless of which replica they hit. Note that for very large tables, this verification step is safer than increasingmutations_synctimeouts, which can lead to connection exhaustion.