É seguro cancelar uma consulta do PostgreSQL ALTER TABLE que está aguardando um bloqueio?

10

Iniciamos uma ALTER TABLEconsulta horas atrás e só recentemente percebemos (via pg_stat_activity) que ela está aguardando um bloqueio. Descobrimos a outra consulta que mantém um bloqueio na tabela que queremos alterar e não o deixamos ir.

Nossa consulta é uma consulta "simples" (alterando o tipo de dados da coluna), mas está sendo executada em uma tabela massiva.

Em vez de matar o processo que está travando, decidimos que preferimos matar o ALTER TABLE.

Nós fez não envolva o ALTER TABLEem uma transação.

Pelo que entendi, o fato de nossa consulta estar aguardando um bloqueio significa que sempre o aguardou e nunca mudou nada.

Isso é verdade? É seguro cancelar completamente nossa ALTER TABLEconsulta? Ou é possível que a consulta já tenha modificado algo e cancelá-lo deixaria nosso banco de dados em um estado intermediário de algum tipo?

PS: O plano é cancelá-lo usando SELECT pg_cancel_backend(pid);. Se for uma má ideia, entre em contato.

JMTyler
fonte
11
Deve ser bom cancelar a ALTER TABLE. O PostgreSQL possui DDL transacional e você deve ficar no mesmo estado como se não tivesse executado a ALTER TABLE.
Josh Kupershmidt
Então, quando você diz que o PostgreSQL possui uma transação DDL, isso significa que qualquer consulta de alteração de esquema é essencialmente executada dentro de uma transação?
JMTyler # 6/15
11
No seu caso, o ALTER TABLE é "essencialmente executado dentro de uma transação", pois você disse "Não envolvemos o ALTER TABLE em uma transação.". Se você quiser, você pode escrever BEGIN; ALTER TABLE foo ...; Barra ALTER TABLE ...; etc; COMMIT; - esse é o verdadeiro recurso matador do PostgreSQL com DDL transacional. Mas, para a sua situação imediata, sim, o ALTER TABLE por si só pode ser cancelado com segurança e será revertido como se nunca tivesse acontecido.
Josh Kupershmidt
Muito obrigado por suas respostas rápidas! Esta é uma informação muito boa. Você poderia publicá-lo como resposta para que eu possa marcá-lo como aceito?
JMTyler #

Respostas:

13

Pelo que entendi, o fato de nossa consulta estar aguardando um bloqueio significa que sempre o aguardou e nunca mudou nada.

Certo - se você perceber que pg_stat_activity.waiting é "verdadeiro" para uma ALTER TABLE, isso quase certamente significa que está aguardando pacientemente o bloqueio ACCESS EXCLUSIVE em sua tabela de destino e seu trabalho real (reescrevendo a tabela, se necessário, alterando catálogos , reconstruir índices etc.) ainda não foi iniciado.

É seguro cancelar completamente nossa consulta ALTER TABLE? Ou é possível que a consulta já tenha modificado algo e cancelá-lo deixaria nosso banco de dados em um estado intermediário de algum tipo?

O cancelamento de consultas (ou, equivalentemente, a reversão de uma transação) no PostgreSQL não apresenta nenhum risco de corrupção de banco de dados que você possa ter assustado em alguns outros bancos de dados (por exemplo, o aviso aterrorizante na parte inferior desta página). É por isso que os não superusuários são, nas versões recentes, livres para usar pg_cancel_backend()e pg_terminate_backend()eliminar suas próprias consultas em execução em outros back-ends - eles podem ser usados ​​com segurança, sem se preocupar com a corrupção do banco de dados. Afinal, o PostgreSQL precisa estar preparado para lidar com qualquer processo que seja eliminado, por exemplo, o SIGKILL do assassino OOM, o desligamento do servidor, etc. É para isso que serve o log do WAL .

Você também deve ter visto que no PostgreSQL, é possível executar a maioria dos comandos DDL aninhados em uma transação (multi-instrução), por exemplo

BEGIN;
ALTER TABLE foo ...;
ALTER TABLE bar ...;
-- more stuff
COMMIT; -- or ROLLBACK; if you've changed your mind

(Impressionante para garantir que as migrações de esquema sejam realizadas juntas ou totalmente.) Você disse:

Nós fez não envolva o ALTER TABLEem uma transação.

Isso é bom para um único comando - dos documentos ,

O PostgreSQL realmente trata cada instrução SQL como sendo executada dentro de uma transação. Se você não emitir um comando BEGIN, cada instrução individual terá um BEGIN implícito e (se bem-sucedido) COMMIT envolvido nele. Às vezes, um grupo de instruções cercado por BEGIN e COMMIT é chamado de bloco de transação.

Portanto, cancelar isso ALTER TABLE, através de pg_cancel_backend()um Ctrl-C ou emitido a partir do prompt psql de controle, terá um efeito semelhante como se você tivesse feito

BEGIN;
ALTER TABLE ... ;
ROLLBACK;

(embora você esperasse ver, cancelar esse caro ALTER TABLEpode salvar o banco de dados de muitas operações desnecessárias, se você quiser ROLLBACK.

Josh Kupershmidt
fonte
5

Para elaborar a resposta correta e excelente de Josh:

É seguro cancelar completamente nossa consulta ALTER TABLE?

Sim.

Seria seguro, mesmo que fosse no meio de reescrever a mesa .

Se você quiser, você pode simplesmente desligar o servidor PostgreSQL inteiro ou, de fato, a máquina na qual ele roda, reiniciá-lo e tudo ficará bem. O DDL no PostgreSQL é transacional e seguro contra falhas.

As operações DDL são registradas no WAL e é garantido que elas podem ser revertidas ou concluídas após a recuperação após uma falha ou abortamento.

Craig Ringer
fonte
3
Apenas uma observação sobre "você pode simplesmente desligar o servidor PostgreSQL inteiro ou, de fato, a máquina em que ele roda, reiniciá-lo e tudo ficaria bem" - é verdade desde que você tenha um hardware confiável que não mente sobre o fsync , wiki.postgresql.org/wiki/Reliable_Writes
Josh Kupershmidt
2
@JoshKupershmidt Claro, mas isso não é específico para DDL. Se você tiver problemas de sincronização, não é seguro para tudo .
Craig Ringer