Épuisement du disque du journal système ClickHouse
Problème
Les tables de journal système interne de ClickHouse (text_log, trace_log, processors_profile_log,
query_log, metric_log, asynchronous_metric_log) se remplissent sans limite avec un TTL par défaut de
180 jours, finissant par remplir le disque entier. Cela provoque l'échec de toutes les opérations INSERT avec
Code: 243 - Cannot reserve 1.00 MiB, not enough space, se propageant simultanément sur toutes les tables d'application.
Contexte / Conditions déclenchantes
- Message d'erreur :
Code: 243. DB::Exception: Cannot reserve 1.00 MiB, not enough space. (NOT_ENOUGH_SPACE) - Symptômes : Tous les écritures échouent simultanément sur plusieurs tables ; les lectures peuvent encore fonctionner
- Pattern Sentry : Plusieurs problèmes d'insertion/commit batch en lot apparaissent en même temps
- Requête de diagnostic :
SELECT database, formatReadableSize(sum(total_bytes)) FROM system.tables WHERE total_bytes > 0 GROUP BY database ORDER BY sum(total_bytes) DESC- Si la base de données
systemest 10 fois ou plus plus volumineuse que les bases de données d'application, c'est la cause
- Si la base de données
- Symptôme supplémentaire ClickHouse Cloud : Les tables avec suffixe numéroté (
trace_log_16,text_log_19) provenant des nœuds serveurs désaffectés s'accumulent et ne sont jamais nettoyées dans la fenêtre TTL
Solution
Diagnostic
-- Vérifier la taille des bases de données
SELECT database, formatReadableSize(sum(total_bytes)) as size
FROM system.tables WHERE total_bytes > 0
GROUP BY database ORDER BY sum(total_bytes) DESC;
-- Trouver les plus grandes tables système
SELECT name, formatReadableSize(total_bytes) as size
FROM system.tables
WHERE database = 'system' AND total_bytes > 100000000
ORDER BY total_bytes DESC LIMIT 20;
-- Vérifier l'utilisation du disque
SELECT name, formatReadableSize(free_space) as free, formatReadableSize(total_space) as total
FROM system.disks WHERE name = 'default';
Correction : ClickHouse auto-hébergé (accès kubectl)
Étape 1 : Si le disque est à 100% plein (TRUNCATE lui-même échoue avec NOT_ENOUGH_SPACE)
TRUNCATE a besoin d'espace disque temporaire. Quand le disque est vraiment à 100%, vous devez d'abord libérer l'espace au niveau du système de fichiers :
# Trouver et supprimer les tables orphelines avec suffixe _N (provenant d'anciens replicas)
kubectl exec $CH_POD -- du -sh /var/lib/clickhouse/data/system/*_0/
# Les détacher d'abord (important !), puis supprimer les données
kubectl exec $CH_POD -- clickhouse-client --query "DETACH TABLE system.text_log_0 PERMANENTLY"
kubectl exec $CH_POD -- bash -c "rm -rf /var/lib/clickhouse/data/system/text_log_0/"
# Répéter pour les autres tables _N jusqu'à avoir ~100 MB+ de libre
Étape 2 : Supprimer les partitions ou tronquer les tables
Les tables de journal système sont partitionnées par toYYYYMM(event_date). Supprimer d'abord les partitions plus anciennes
(opérations plus petites), puis tronquer :
-- Vérifier les partitions
SELECT partition, formatReadableSize(sum(bytes_on_disk)) as size
FROM system.parts
WHERE database = 'system' AND table = 'text_log' AND active
GROUP BY partition ORDER BY partition;
-- Supprimer les anciennes partitions une à la fois
ALTER TABLE system.text_log DROP PARTITION 202601 SETTINGS max_partition_size_to_drop = 0;
ALTER TABLE system.text_log DROP PARTITION 202602 SETTINGS max_partition_size_to_drop = 0;
-- Ou tronquer les tables entières (nécessite l'override max_table_size_to_drop si > 50 GB)
TRUNCATE TABLE system.text_log SETTINGS max_table_size_to_drop = 0;
TRUNCATE TABLE system.trace_log SETTINGS max_table_size_to_drop = 0;
TRUNCATE TABLE system.processors_profile_log SETTINGS max_table_size_to_drop = 0;
TRUNCATE TABLE system.query_log SETTINGS max_table_size_to_drop = 0;
TRUNCATE TABLE system.metric_log SETTINGS max_table_size_to_drop = 0;
TRUNCATE TABLE system.asynchronous_metric_log SETTINGS max_table_size_to_drop = 0;
Étape 3 : Configurer le TTL pour éviter la récurrence
-- Définir un TTL de 3 jours sur toutes les principales tables de journal système
ALTER TABLE system.text_log MODIFY TTL event_date + INTERVAL 3 DAY SETTINGS materialize_ttl_after_modify = 0;
ALTER TABLE system.trace_log MODIFY TTL event_date + INTERVAL 3 DAY SETTINGS materialize_ttl_after_modify = 0;
ALTER TABLE system.processors_profile_log MODIFY TTL event_date + INTERVAL 3 DAY SETTINGS materialize_ttl_after_modify = 0;
ALTER TABLE system.query_log MODIFY TTL event_date + INTERVAL 7 DAY SETTINGS materialize_ttl_after_modify = 0;
ALTER TABLE system.metric_log MODIFY TTL event_date + INTERVAL 3 DAY SETTINGS materialize_ttl_after_modify = 0;
ALTER TABLE system.asynchronous_metric_log MODIFY TTL event_date + INTERVAL 3 DAY SETTINGS materialize_ttl_after_modify = 0;
ALTER TABLE system.part_log MODIFY TTL event_date + INTERVAL 3 DAY SETTINGS materialize_ttl_after_modify = 0;
ALTER TABLE system.query_views_log MODIFY TTL event_date + INTERVAL 3 DAY SETTINGS materialize_ttl_after_modify = 0;
Correction : ClickHouse Cloud (pas d'accès shell)
ClickHouse Cloud révoque toutes les permissions de modification sur system.* des rôles créés par l'utilisateur :
REVOKE INSERT, ALTER, CREATE TABLE, DROP TABLE, TRUNCATE, OPTIMIZE ON system.* FROM default_role
Vous NE POUVEZ PAS corriger ceci via SQL. Les seules options sont :
- Console ClickHouse Cloud (https://clickhouse.cloud/) : Accéder aux paramètres du service et réduire les TTL des journaux système à 3-7 jours
- Obtenir le mot de passe de l'utilisateur
defaultdepuis la console, puis exécuter les commandes ALTER TTL - Support ClickHouse Cloud : Demander un nettoyage des journaux système
Pour identifier ClickHouse Cloud : chercher les tables avec suffixe numéroté (par exemple, trace_log_16,
text_log_19) provenant des pods serveur en rotation. Aussi, system.disks affichera
des chemins system-tables/mergetree/ avec 16 EiB (stockage objet).
Vérification
-- Après le nettoyage, vérifier l'utilisation du disque
-- Auto-hébergé :
SELECT formatReadableSize(free_space) FROM system.disks WHERE name = 'default';
-- Les deux : vérifier que la base système est maintenant petite
SELECT database, formatReadableSize(sum(total_bytes)) as size
FROM system.tables WHERE total_bytes > 0 GROUP BY database;
-- Tester que les écritures fonctionnent
INSERT INTO your_table (...) VALUES (...);
Notes
- La limite de sécurité
max_table_size_to_dropest par défaut 50 GB. Les tables plus volumineuses que cela nécessitentSETTINGS max_table_size_to_drop = 0pour tronquer/supprimer. - Quand le disque est vraiment à 100%, même les opérations DDL échouent. Vous DEVEZ d'abord libérer l'espace au niveau du système de fichiers (détacher + supprimer les tables orphelines, ou supprimer les fichiers tmp).
DETACH TABLE ... PERMANENTLYest important avant de supprimer les fichiers de données - cela empêche ClickHouse d'essayer d'accéder aux fichiers supprimés.materialize_ttl_after_modify = 0empêche ClickHouse d'essayer immédiatement de réécrire toutes les données pour appliquer le TTL (ce qui nécessiterait l'espace disque que vous n'avez pas).- Sur ClickHouse Cloud, chaque rotation de nœud serveur laisse derrière elle des tables de journal système numérotées
(par exemple,
_16,_19) qui s'accumulent au fil du temps. Avec 65+ nœuds sur des mois, cela s'ajoute à des dizaines de GB. - Le
text_logest typiquement le principal responsable car il enregistre au niveau trace/debug par défaut et inclut chaque ligne de journal du serveur ClickHouse.
Références
- Documentation des tables système ClickHouse : https://clickhouse.com/docs/en/operations/system-tables
- Documentation TTL ClickHouse : https://clickhouse.com/docs/en/engines/table-engines/mergetree-family/mergetree#table_engine-mergetree-ttl
- max_table_size_to_drop ClickHouse : https://clickhouse.com/docs/en/operations/settings/settings#max-table-size-to-drop