Saltar para o conteúdo
EuroVPSEuroVPS

Nunca reinicie um mistério: o que registar antes de um reinício

Um reinício apaga o sintoma e, com ele, as evidências. Num sistema stateful, os cinco minutos gastos a registar o estado antes decidem se os dados sobrevivem.

Por EuroVPS EngineeringA casa das máquinas

6 min de leitura
Neste artigo 6 secções
Em resumo
  • Reiniciar um serviço stateless é uma correção. Reiniciar um serviço stateful antes de a causa ser conhecida é uma experiência feita sobre os seus dados, e uma paragem suja é o mecanismo pelo qual alguns table engines se corrompem.
  • Um reboot apaga o estado dos processos, os donos dos sockets, o ring buffer do kernel e a distinção entre um crash e um arranque falhado. Registe-os primeiro. Demora minutos.
  • Snapshot antes da reparação, reparação antes do restore, e verificação na fronteira que falhou e não em «o serviço está em cima».

Onde o reflexo está certo, e onde não está

Desligar e voltar a ligar funciona num web worker encravado, num consumidor de fila preso, num portátil. O estado que estava errado é descartado e reconstruído do nada, porque nada de valor vivia nele. Bases de dados, message brokers, storage daemons e tudo o que tenha um write-ahead log são o caso oposto. O estado é o produto. Um reinício não descarta o estado mau. Descarta a informação sobre como ficou mau, e em alguns engines acrescenta danos próprios.

O que um reinício apaga

A tabela de processos e os seus tempos: que processo corre desde quando, qual está em uninterruptible sleep e à espera de quê. O dono de cada socket e file handle aberto, que lhe diz quem segurava o lock ou a porta. O ring buffer do kernel, que numa instalação por omissão não sobrevive a um reboot e é onde um out-of-memory kill, um erro de filesystem ou um disco a falhar se anunciam. O conteúdo da memória do serviço, que um core dump pode preservar e um reinício não. A cronologia de encerramento e arranque que separa um crash de um arranque falhado. E num table engine sem crash recovery, a própria paragem suja é a forma como um cabeçalho de índice fica danificado, pelo que o reinício destinado a corrigir o serviço pode ser o evento que corrompe as tabelas.

O kit de evidências, em minutos

Tudo o que se segue é read-only. Execute-o a partir de uma shell na máquina, redirecione a saída para um ficheiro com marca temporal e copie esse ficheiro para fora da máquina antes de alguém tocar em mais alguma coisa.

TERMINAL
$ uptime; last -x | head -20; journalctl --list-boots | tail -3
$ dmesg -T | tail -200
$ ps -eo pid,ppid,stat,etime,wchan:24,cmd --sort=-etime | head -60
$ ss -tnp state established | head -100
$ free -m; df -h; df -i
$ vmstat 1 5
$ top -b -n 1 | head -40

Para uma base de dados, acrescente a visão que o próprio engine tem de si mesmo enquanto ainda responde, e a cauda do seu error log quer responda quer não.

TERMINAL
mysql> SHOW FULL PROCESSLIST;
mysql> SHOW ENGINE INNODB STATUS\G
mysql> SHOW GLOBAL STATUS LIKE 'Threads_%';
$ tail -500 /var/log/mariadb/mariadb.log

O primeiro bloco responde se a máquina já reiniciou, se o kernel matou alguma coisa, o que está preso e à espera de quê, quem detém que ligação, e se a máquina está sob pressão de memória ou de I/O. O segundo responde ao que a base de dados pensa que está a acontecer: uma transação longa a segurar locks, um thread de replicação parado, um deadlock, uma tabela reportada como crashed.

Crash, ou arranque falhado

A distinção mais útil no log é entre um serviço que teve um crash e um serviço que encerrou de forma limpa e depois não conseguiu voltar. O primeiro precisa de que o gatilho seja encontrado antes de se reiniciar o que quer que seja, porque reiniciar com um gatilho ativo reproduz o crash. O segundo é um problema de arranque ou de política: uma configuração alterada, um disco cheio, uma permissão, uma unit que não estava enabled. Os dados não estão em risco no segundo caso, e tratá-lo como um crash desperdiça o tempo que teria trazido o serviço de volta. A cauda do log do serviço mostra qual dos dois é: uma linha de encerramento concluído seguida de um abort no arranque é o segundo caso.

O caminho reversível

Assim que o gatilho é conhecido, a sequência é a mesma em todos os sistemas stateful. Pare o gatilho, para que a correção não possa ser desfeita por outro crash a meio da recuperação. Tire o snapshot gratuito: pare as escritas, renomeie o diretório de dados para o lado ou faça snapshot do volume, e guarde uma cópia fora da máquina. A partir desse ponto, cada passo pode ser revertido. Repare antes de fazer restore, porque um backup transporta fielmente o que o sistema transportava no momento em que foi feito, e se a falha entrou com os dados, o restore volta a plantá-la enquanto descarta tudo o que foi escrito desde então. Verifique na fronteira que falhou: a query que abortou, a tabela que reportou zero linhas, a posição de replicação, não apenas que a porta está aberta. Aplique o tuning planeado só depois de o paciente estar saudável. Recuperação e alteração são duas operações diferentes.

O reflexoO que acontece realmente
Reiniciar o serviçoCom o gatilho ainda ativo volta a ter um crash, e a segunda paragem é tão suja como a primeira
Restore de ontem à noiteTudo o que foi escrito desde ontem à noite desaparece, e uma falha que entrou com os dados é reposta com eles
Acrescentar memória, parece memóriaSe o abort é software a percorrer metadados danificados, o hardware não muda nada
Teve um crash, logo algo está avariadoUm encerramento limpo seguido de um arranque falhado é um problema de reinício sem dados em risco

Uma contagem de linhas a zero depois de um hard reboot é habitualmente um índice danificado sobre linhas intactas. Em engines sem crash recovery, uma reparação reconstrói o índice a partir dos dados. Um restore deita os dados fora.

A cura, distinta da recuperação

Uma reparação é recuperação. A cura é remover o que quer que cause paragens sujas, e converter as tabelas que não sobrevivem a uma para um engine que sobrevive. Ambas pertencem ao seguimento, não ao combate ao incêndio.

Respostas diretas

Devo reiniciar a minha base de dados que teve um crash?+

Não até o log lhe ter dito se teve um crash ou falhou ao arrancar, e qual foi o gatilho. Reiniciar com um gatilho ativo reproduz o crash e, num engine que não é crash-safe, pode danificar tabelas. Registe em modo read-only primeiro, depois decida.

A minha tabela mostra zero linhas depois de um crash. Os dados desapareceram?+

Muitas vezes não. Em table engines sem crash recovery, uma paragem suja danifica o cabeçalho do índice enquanto as linhas permanecem no disco, e o engine reporta a contagem a partir do cabeçalho. Faça snapshot do diretório de dados, depois execute a reparação do engine. Uma reparação reconstrói tipicamente o índice a partir das linhas que ainda lá estão. Faça restore apenas se a reparação falhar.

O restore a partir de backup é a recuperação mais segura?+

É habitualmente a mais destrutiva. Tudo o que foi escrito desde o backup é descartado, e se a falha já estava nos dados quando o backup correu, volta com ele. O restore é o último passo, depois do diagnóstico e da reparação.

O que deve ser registado antes de alguém reiniciar o que quer que seja?+

A tabela de processos com tempos, os donos dos sockets abertos, o ring buffer do kernel, a pressão de memória e de I/O, a utilização de disco e de inodes, o histórico de arranques, e o estado e o error log do próprio serviço. Escritos num ficheiro e copiados para fora da máquina. Demora minutos, e é a única cópia dessas evidências que vai ter.

Em baixo neste momento, com o dedo no botão de reiniciar?

Fale com um engenheiro. Diagnosticamos primeiro em modo read-only e fazemos snapshot antes de qualquer coisa que escreva.

Fale com um engenheiro

Chegou ao fim.

Ponha a leitura em prática

O que executa?

Fale-nos da carga de trabalho, do tráfego e dos requisitos de recuperação. Comece pelo configurador de servidores ou discuta os detalhes com um engenheiro.

Escrito pelos engenheiros que constroem e operam a infraestrutura que descreve.
Fale com um engenheiro
XIn

Faltam 6 min