# Utrata danych w ClickHouse: deduplikacja i materialized views
W ClickHouse przy korzystaniu z materialized views dane w tabeli docelowej mogą nie zgadzać się z źródłowymi. Dzieje się tak z powodu deduplikacji bloków podczas INSERT, szczególnie w zreplikoowanych klastrach. Domyślna konfiguracja powoduje ignorowanie bloków przy powtarzanych wstawieniach, co narusza oczekiwania dotyczące magazynu append-only. Rozwiązanie polega na dostosowaniu ustawień insert_deduplicate i deduplicate_blocks_in_dependent_materialized_views.
Rozważmy typowy 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;
Dane z source_table są kopiowane do final_table, ale z czasem w final_table znikają rekordy bez widocznej przyczyny.
Atomowość INSERT w szczegółach
INSERT w ClickHouse dzieli dane na bloki zgodnie z ustawieniem max_insert_block_size. Atomowość jest gwarantowana tylko dla pojedynczego bloku w jednej partycji tabeli MergeTree. Jeśli INSERT zostanie przerwany, ClickHouse próbuje powtórzyć wstawienie brakujących bloków bez powiadamiania użytkownika.
Przy ponownej próbie uruchamia się deduplikacja: każdemu blokowi przypisywany jest block_id jako hash zawartości. Jeśli taki block_id jest już w dzienniku deduplikacji, cały blok jest pomijany. W rezultacie:
- Część danych z oryginalnego INSERT ginie.
- Materialized view nie otrzymuje pełnych danych.
Warunki atomowości:
- Wstawianie do jednej partycji.
- Brak równoległych INSERT do tej samej partycji.
- Dane spakowane w pojedynczy blok.
Niezachowanie tych warunków prowadzi do częściowego wstawienia i deduplikacji przy powtórce.
Mechanizm deduplikacji bloków
Deduplikacja działa na poziomie bloków w zreplikoowanych tabelach MergeTree. Ustawienie insert_deduplicate (domyślnie 1) włącza sprawdzanie block_id. Po wykryciu duplikatu blok jest ignorowany.
W tabelach non-replicated deduplikacja jest wyłączona (non_replicated_deduplication_window=0). W przypadku replikacji zaleca się ustawienie:
insert_deduplicate = 0
Pozwala to uniknąć utraty bloków przy powtarzanych INSERT, choć dopuszcza duplikaty. W obciążeniach analitycznych z append-only duplikaty są akceptowalne i usuwane podczas merges.
Deduplikacja w materialized views
Materialized views wykonują INSERT do tabeli docelowej na podstawie danych ze źródła. Domyślnie deduplikacja jest sprawdzana w tabeli źródłowej, a status przenoszony na view.
Ustawienie deduplicate_blocks_in_dependent_materialized_views kontroluje zachowanie:
- Wartość 0 (domyślnie): deduplikacja w source_table, ryzyko strat.
- Wartość 1: deduplikacja w final_table, bloki wstawiane w całości.
Ustaw:
SET deduplicate_blocks_in_dependent_materialized_views = 1;
Dokumentacja ClickHouse wyraźnie ostrzega: bez korekt materialized views mogą nie otrzymać danych przy powtarzanych wstawieniach bloków.
Zalecenia dotyczące ustawień
Aby wyeliminować utratę danych, wprowadź następujące zmiany w konfiguracji serwera lub sesji:
insert_deduplicate = 0— wyłączenie deduplikacji przy powtarzanych INSERT.deduplicate_blocks_in_dependent_materialized_views = 1— deduplikacja w MV na tabeli docelowej.- Sprawdź max_insert_block_size: duże wartości minimalizują podział na bloki.
- Unikaj równoległych INSERT do jednej partycji.
Monitoruj logi pod kątem częściowych wstawień i porównuj COUNT(*) między tabelami source i final.
Co ważne
- ClickHouse gwarantuje ACID tylko dla pojedynczego bloku w jednej partycji, reszta zależy od ustawień.
- Deduplikacja bloków po block_id powoduje straty przy przerwanych INSERT w pipeline'ach MV.
- Wyłączenie insert_deduplicate rozwiązuje problem dla zreplikoowanych MergeTree.
- Włączenie deduplicate_blocks_in_dependent_materialized_views=1 zapobiega stratom w views.
- Duplikaty po wyłączeniu deduplikacji są usuwane standardowymi merges.
— Editorial Team
Brak komentarzy.