Skip to main content
O canário de OOM é experimental e está desabilitado por padrão. Seu comportamento pode mudar entre versões do ClickHouse até que a validação em produção seja concluída.

Visão geral

Quando um host ou cgroup de memória fica sem memória, o OOM killer (out-of-memory) do Linux encerra um processo com SIGKILL — geralmente o maior consumidor, que, em um host dedicado, é o próprio clickhouse-server. Assim, o servidor inteiro é perdido em vez de ter a chance de se recuperar. O canário de OOM muda quem morre primeiro. Ele executa um pequeno processo filho sacrificial que se torna o alvo de OOM mais atraente, para que o kernel o mate em vez do servidor. O servidor então detecta a morte, confirma que foi um evento de OOM e reduz a pressão de memória para conseguir sobreviver. O canário não aumenta nenhum limite de memória e não substitui limites corretos (veja Memory overcommit e max_server_memory_usage). Ele é a última linha de defesa: troca uma pequena quantidade fixa de memória por uma chance de sobreviver a um pico de uso de memória.

Como funciona

O canário é um processo clickhouse oom-canary separado. Ele ajusta seu próprio oom_score_adj para o valor máximo (1000) para que o kernel o escolha primeiro e, em seguida, aloca, acessa e aplica mlock a oom_canary_size bytes (100 MB por padrão), para que seu conjunto de memória residente seja real. Ele é encerrado automaticamente se o servidor for encerrado. No servidor, uma thread de monitoramento observa o canário (via pidfd) e reage quando ele morre:
  • Encerrado por SIGKILL com evidência de OOM no cgroup → executa a resposta a OOM e, em seguida, relança um novo canário.
  • Encerrado sem evidência de OOM (por exemplo, um kill -9 manual), ou encerrado com uma falha transitória → apenas relança, sem resposta.
  • Falha permanente na inicialização, ou desligamento do servidor → o canário se desativa.
A evidência de OOM vem apenas do contador oom_kill de memory.events.local do cgroup v2. Ela é deliberadamente local ao cgroup: contadores hierárquicos ou de todo o host podem ser incrementados por processos não relacionados e acionariam respostas indevidas. Em um OOM confirmado, a resposta executa estas etapas independentes: registrar uma mensagem FATAL, limpar as arenas do alocador (jemalloc), tentar cancelar todas as consultas em execução, cancelar todas as mesclagens e mutações e enfileirar um evento em system.crash_log. Os logs do sistema não são gravados de forma síncrona, porque forçar E/S sob pressão de memória pode piorar a situação.

Requisitos

  • Linux ≥ 5.3. O monitor mantém controle do canário via pidfd_open; em kernels mais antigos, o canário se desativa na inicialização. Isso é um no-op em plataformas que não sejam Linux.
  • cgroup v2 com memory.events.local para a resposta a OOM. Sem isso, o canário ainda é reiniciado após um SIGKILL, mas não consegue confirmar um OOM; portanto, a resposta nunca é executada (um aviso é registrado na inicialização).
  • capacidade de mlock (opcional). Bloquear a memória do canário exige CAP_IPC_LOCK ou um RLIMIT_MEMLOCK suficiente; se isso falhar, o canário registra um aviso, e sua memória pode ir para swap, enfraquecendo-o como alvo de OOM.
memory.oom.groupSe memory.oom.group do cgroup v2 estiver habilitado para o cgroup do servidor, o kernel elimina o cgroup inteiro como uma única unidade em um OOM — o servidor morre junto com o canário, e a resposta nunca é executada. O canário não pode proteger o servidor nesse modo; um aviso é registrado na inicialização.

Configuração

O canário é controlado por configurações do servidor, definidas como elementos de nível superior da configuração do servidor e aplicadas após reinicialização.

Observabilidade

Um OOM confirmado gera uma linha em system.crash_log com signal = 9 e uma signal_description mencionando OOM Canary:
O ciclo de vida do canário e cada etapa da resposta a OOM também são registrados no log do servidor.
Última modificação em 24 de julho de 2026