Sổ tay kỹ thuật

ClickHouse – xử lý sự cố vận hành

troubleshooting#clickhouse#akvorado#linux· cập nhật 2026-11-06

Xử lý TOO_MANY_PARTS, vượt memory limit, merge/mutation bị kẹt, đầy disk và query chậm bằng system tables.

Sửa trang này
Mục lục

Triệu chứng chính: insert bị từ chối với Too many parts (...). Merges are processing significantly slower than inserts (TOO_MANY_PARTS), query báo Memory limit (for query) exceeded ... (MEMORY_LIMIT_EXCEEDED), disk đầy, hoặc dashboard flow (Akvorado) load rất chậm.

Lỗi thường gặp

Triệu chứng Nguyên nhân Cách xử lý
Too many parts (...) ... (TOO_MANY_PARTS) Insert nhiều batch nhỏ, mỗi insert tạo một part; merge không theo kịp Gom batch lớn hơn (≥ vài nghìn dòng, ≤ 1 insert/giây/bảng), hoặc bật async_insert = 1
Như trên, partition quá nhỏ PARTITION BY quá chi tiết (theo giờ, theo exporter) Partition theo ngày/tháng; chỉ tăng parts_to_throw_insert khi đã hiểu rõ
Memory limit (for query) exceeded: would use ... (MEMORY_LIMIT_EXCEEDED) GROUP BY cardinality cao, JOIN bảng lớn Lọc thời gian chặt hơn, max_bytes_before_external_group_by, đặt bảng nhỏ bên phải JOIN
Memory limit (total) exceeded Tổng RAM server vượt max_server_memory_usage Giảm query song song, kiểm tra merge lớn trong system.merges
Cannot reserve ..., not enough space (NOT_ENOUGH_SPACE) Disk đầy, merge cần chỗ trống bằng tổng kích thước part nguồn Xoá partition cũ, đặt TTL, mở rộng disk
Timeout exceeded: elapsed ... (TIMEOUT_EXCEEDED) Query quét quá nhiều dữ liệu Thêm điều kiện trên cột của ORDER BY/partition, dùng bảng tổng hợp
Too many simultaneous queries Dashboard refresh dày, nhiều người xem Tăng refresh interval Grafana, cache, max_concurrent_queries
Table is in readonly mode Bảng Replicated mất kết nối ZooKeeper/Keeper Kiểm tra Keeper, system.replicas.is_readonly
Mutation (ALTER ... DELETE/UPDATE) không xong Mutation lỗi hoặc rất nặng Xem system.mutations.latest_fail_reason, KILL MUTATION

Các bước khoanh vùng

  1. Lỗi gần đây là gì: system.errors và log server.
  2. Part và merge: số part active mỗi partition, merge đang chạy.
  3. Disk: system.disks, dung lượng theo bảng (system.parts).
  4. Query: query nặng nhất trong system.query_log, query đang chạy trong system.processes.
  5. Sửa: chỉnh batch insert / TTL / query, rồi theo dõi lại.

OPTIMIZE TABLE ... FINAL ép merge toàn bộ, rất tốn IO và cần nhiều disk trống. Không dùng làm cách sửa TOO_MANY_PARTS trên bảng lớn trong giờ cao điểm.

Kiểm tra nhanh

-- Lỗi gần nhất
SELECT name, value, last_error_time, last_error_message
FROM system.errors ORDER BY last_error_time DESC LIMIT 10;
 
-- Số part active theo partition (cảnh báo khi lên hàng trăm)
SELECT database, table, partition, count() AS parts, sum(rows) AS rows
FROM system.parts WHERE active
GROUP BY database, table, partition ORDER BY parts DESC LIMIT 20;
 
-- Merge đang chạy
SELECT database, table, round(elapsed) AS sec, round(progress * 100) AS pct,
       num_parts, formatReadableSize(memory_usage) AS mem
FROM system.merges;
 
-- Mutation chưa xong
SELECT database, table, mutation_id, command, latest_fail_reason
FROM system.mutations WHERE NOT is_done;
 
-- Disk
SELECT name, path, formatReadableSize(free_space) AS free, formatReadableSize(total_space) AS total
FROM system.disks;
 
-- Dung lượng theo bảng, tỉ lệ nén
SELECT table,
       formatReadableSize(sum(data_compressed_bytes)) AS compressed,
       formatReadableSize(sum(data_uncompressed_bytes)) AS raw,
       round(sum(data_uncompressed_bytes) / sum(data_compressed_bytes), 1) AS ratio
FROM system.parts WHERE active
GROUP BY table ORDER BY sum(data_compressed_bytes) DESC;
 
-- 10 query nặng nhất 1 giờ qua (cùng dạng query gom lại)
SELECT normalized_query_hash, count() AS n,
       round(avg(query_duration_ms)) AS avg_ms,
       formatReadableSize(max(memory_usage)) AS max_mem,
       formatReadableSize(sum(read_bytes)) AS read,
       any(query) AS sample
FROM system.query_log
WHERE type = 'QueryFinish' AND event_time > now() - INTERVAL 1 HOUR
GROUP BY normalized_query_hash ORDER BY sum(query_duration_ms) DESC LIMIT 10;
 
-- Query đang chạy
SELECT query_id, user, round(elapsed) AS sec, formatReadableSize(memory_usage) AS mem, query
FROM system.processes ORDER BY elapsed DESC;
 
-- Query có dùng primary key / partition pruning không
EXPLAIN indexes = 1
SELECT count() FROM flows WHERE TimeReceived > now() - INTERVAL 1 HOUR;

Lệnh xử lý:

KILL QUERY WHERE query_id = '<id>';
KILL MUTATION WHERE mutation_id = '<id>';
ALTER TABLE flows DROP PARTITION '<partition-id>';         -- lấy tên từ system.parts.partition
ALTER TABLE flows MODIFY TTL TimeReceived + INTERVAL 30 DAY;
SYSTEM FLUSH LOGS;                                          -- ghi query_log ngay
SELECT * FROM flows WHERE TimeReceived > now() - INTERVAL 1 HOUR
SETTINGS max_memory_usage = 8000000000, max_execution_time = 60;
journalctl -u clickhouse-server -n 200 --no-pager
tail -n 200 /var/log/clickhouse-server/clickhouse-server.err.log
df -h /var/lib/clickhouse && du -sh /var/lib/clickhouse/store

Query top talkers mẫu xem ClickHouse top talkers. Xử lý disk đầy ở tầng OS xem disk đầy.