Datenverlust in ClickHouse: Deduplizierung und materialisierte Ansichten
In ClickHouse können bei der Verwendung materialisierter Ansichten die Daten in der Zieltabelle nicht mit der Quelle übereinstimmen. Dies geschieht durch Block-Deduplizierung während INSERT, insbesondere in replizierten Clustern. Die Standardkonfiguration führt dazu, dass Blöcke bei wiederholten Einfügungen ignoriert werden, was die Erwartungen an append-only-Speicherung zunichtemacht. Die Lösung besteht darin, die Einstellungen insert_deduplicate und deduplicate_blocks_in_dependent_materialized_views anzupassen.
Betrachten Sie einen typischen Pipeline:
CREATE TABLE source_table (
message String
) engine=MergeTree()
ORDER BY (message);
CREATE TABLE final_table (
message String
) engine=MergeTree()
ORDER BY (message);
CREATE MATERIALIZED VIEW mv_source_table TO final_table AS
SELECT
message
FROM source_table;
Daten aus source_table werden in final_table kopiert, aber mit der Zeit verschwinden Datensätze aus final_table ohne ersichtlichen Grund.
Atomicität von INSERT im Detail
ClickHouse teilt INSERT-Daten basierend auf der Einstellung max_insert_block_size in Blöcke auf. Atomicität wird nur für einen einzelnen Block in einer MergeTree-Tabellenpartition garantiert. Bei Unterbrechung eines INSERTs versucht ClickHouse, die fehlenden Blöcke erneut einzufügen, ohne den Benutzer zu benachrichtigen.
Beim Wiederholungsversuch greift die Deduplizierung: Jeder Block erhält eine block_id als Hash seines Inhalts. Ist diese block_id bereits im Deduplizierungsprotokoll vorhanden, wird der gesamte Block übersprungen. Ergebnis:
- Ein Teil der Daten aus dem ursprünglichen INSERT geht verloren.
- Die materialisierte Ansicht erhält nicht die vollständigen Daten.
Bedingungen für Atomicität:
- Einfügen in eine einzige Partition.
- Keine gleichzeitigen INSERTs in dieselbe Partition.
- Daten in einem einzigen Block gepackt.
Nicht-Erfüllung dieser Bedingungen führt zu partiellen Einfügungen und Deduplizierung beim Wiederholungsversuch.
Mechanismus der Block-Deduplizierung
Die Deduplizierung arbeitet auf Blockebene in replizierten MergeTree-Tabellen. Die Einstellung insert_deduplicate (standardmäßig 1) aktiviert block_id-Überprüfungen. Bei Fund eines Duplikats wird der Block ignoriert.
In nicht replizierten Tabellen ist Deduplizierung deaktiviert (non_replicated_deduplication_window=0). Für Replikation wird empfohlen:
insert_deduplicate = 0
Dies verhindert Blockverluste bei wiederholten INSERTs, erlaubt aber Duplikate. Bei analytischen append-only-Workloads sind Duplikate akzeptabel und werden während der Merges bereinigt.
Deduplizierung in materialisierten Ansichten
Materialisierte Ansichten führen INSERTs in die Zieltabelle basierend auf Quellendaten durch. Standardmäßig wird Deduplizierung auf der Quelltabelle geprüft, und der Status wird auf die Ansicht übertragen.
Die Einstellung deduplicate_blocks_in_dependent_materialized_views steuert dies:
- 0 (Standard): Deduplizierung auf
source_table, Risiko von Datenverlust. - 1: Deduplizierung auf
final_table, Blöcke vollständig eingefügt.
Legen Sie fest:
SET deduplicate_blocks_in_dependent_materialized_views = 1;
Die ClickHouse-Dokumentation warnt ausdrücklich, dass materialisierte Ansichten bei wiederholten Blockeinfügungen Daten verpassen können, wenn keine Anpassungen vorgenommen werden.
Empfohlene Einstellungen
Um Datenverlust zu eliminieren, wenden Sie diese Änderungen in der Server- oder Sitzungskonfiguration an:
insert_deduplicate = 0— Deduplizierung bei wiederholten INSERTs deaktivieren.deduplicate_blocks_in_dependent_materialized_views = 1— Deduplizierung in MV auf der Zieltabelle.- Überprüfen Sie
max_insert_block_size: Größere Werte minimieren die Blockaufteilung. - Vermeiden Sie gleichzeitige INSERTs in dieselbe Partition.
Überwachen Sie Logs auf partielle Einfügungen und vergleichen Sie COUNT(*) zwischen Quell- und Zieltabelle.
Wichtige Erkenntnisse
- ClickHouse garantiert ACID nur für einen einzelnen Block in einer Partition; alles andere hängt von Einstellungen ab.
- Block-Deduplizierung per
block_idverursacht Verluste bei unterbrochenen INSERTs in MV-Pipelines. - Das Deaktivieren von
insert_deduplicatelöst das Problem für replizierte MergeTree. - Das Setzen von
deduplicate_blocks_in_dependent_materialized_views=1verhindert Verluste in Ansichten. - Duplikate nach Deaktivierung der Deduplizierung werden durch Standard-Merges entfernt.
— Editorial Team
Noch keine Kommentare.