Desenvolvimento e bases de dados

Terminar consultas MySQL em execução

Revisto a 6 min de leitura MySQL consultas

Por vezes, uma consulta SQL demora muito mais do que o esperado, por uma falha da aplicação ou por ser muito pesada. Se, além disso, bloquear a tabela, as restantes consultas ficam à espera e o site fica pendurado. Nesse caso, pode terminar a consulta manualmente.

Há duas formas de a terminar:

  • KILL QUERY id para apenas a consulta e deixa a ligação aberta. É a opção recomendada.
  • KILL id (e mysqladmin kill id) fecha a ligação inteira, o que desfaz qualquer transação que estivesse a meio.

A partir do terminal

Ligue-se por SSH à conta. Se tiver experiência, use o terminal do seu equipamento; caso contrário, o terminal integrado no cPanel é mais simples.

Com consultas SQL

Entre no MySQL com um utilizador que tenha permissões sobre a base de dados:

mysql -u usuario_mysql -p

Ser-lhe-á pedida a palavra-passe. Não a escreva no próprio comando (-pcontraseña), porque ficaria no histórico do terminal.

Liste os processos abertos:

SHOW FULL PROCESSLIST;

Verá uma tabela com cada ligação, o seu utilizador, base de dados, estado, segundos que leva (Time) e a consulta (Info):

Resultado de SHOW FULL PROCESSLIST com as consultas em execução

As linhas com Command em Sleep são ligações inativas sem consulta em curso: normalmente não é preciso mexer nelas. A que procura costuma ter um Time alto e um estado como Sending data, Locked ou Waiting for table metadata lock.

Anote o valor da coluna Id da consulta que quer terminar e execute:

KILL QUERY 12345;

Volte a executar SHOW FULL PROCESSLIST; e confirme que já não aparece. Se continuar lá com o estado Killed, está a desfazer alterações: aguarde alguns segundos. Se mesmo assim não terminar, feche a ligação inteira com KILL 12345;.

Terminar todas as consultas de um utilizador

Se houver muitas consultas acumuladas do mesmo utilizador, esta consulta gera as instruções para as terminar todas. Substitua USUARIO_MYSQL pelo utilizador que as executa:

SELECT GROUP_CONCAT(CONCAT('KILL QUERY ', ID, ';') SEPARATOR ' ')
FROM information_schema.PROCESSLIST
WHERE USER = 'USUARIO_MYSQL'
  AND COMMAND <> 'Sleep'
  AND ID <> CONNECTION_ID();

Copie o resultado (algo como KILL QUERY 101; KILL QUERY 102; ...), cole-o e execute-o. A condição ID <> CONNECTION_ID() evita que termine a sua própria sessão, e COMMAND <> 'Sleep' exclui as ligações inativas.

Para terminar apenas as consultas que contêm um texto, por exemplo as que atuam sobre uma tabela, acrescente mais um filtro:

  AND INFO LIKE '%wp_options%'

No alojamento só verá e poderá terminar as consultas dos seus próprios utilizadores MySQL.

Com o mysqladmin

A partir do terminal, também pode usar o mysqladmin sem entrar no MySQL. Liste os processos:

mysqladmin -u usuario_mysql -p processlist

E termine o que quiser com o respetivo identificador:

mysqladmin -u usuario_mysql -p kill 12345

Pode indicar vários separados por vírgulas: kill 101,102,103. Tenha em conta que mysqladmin kill fecha a ligação inteira, não apenas a consulta.

Para terminar de uma só vez todas as consultas que contenham um texto (o nome de uma tabela, de uma base de dados...), combine a lista com o awk:

mysqladmin -u usuario_mysql -p processlist | awk -F'|' '/TEXTO_A_FILTRAR/ && $6 !~ /Sleep/ {gsub(/ /,"",$2); print $2}' | paste -sd, - | xargs -r mysqladmin -u usuario_mysql -p kill

O comando pede a palavra-passe duas vezes: uma para listar e outra para terminar. Antes de o lançar, execute apenas a primeira parte (até paste) para ver que identificadores vai terminar.

A partir do phpMyAdmin

Aceda ao phpMyAdmin, selecione a base de dados e abra o separador SQL. Escreva:

SHOW FULL PROCESSLIST;

O phpMyAdmin mostra a tabela de processos com uma ligação Kill junto a cada um para o terminar com um clique:

Lista de processos no phpMyAdmin com a opção para terminar cada consulta

Também tem a mesma lista em Status > Processes (Estado > Processos). A ligação do phpMyAdmin fecha a ligação inteira; se quiser parar apenas a consulta, escreva KILL QUERY id; no separador SQL.

Se voltar a acontecer

Terminar a consulta resolve o bloqueio, mas não a causa. Se a mesma consulta ficar pendurada com frequência, costuma faltar um índice na tabela ou há um plugin ou tarefa programada que a lança demasiadas vezes. Veja o texto da coluna Info para saber o que a gera.

Mais detalhes na documentação do MySQL sobre KILL.

Também lhe pode ser útil

Algo não bate certo ou mudou? Diga-nos e revemos.