Est-il sûr d'annuler une requête ALTER TABLE PostgreSQL qui attend un verrou?

10

Nous avons lancé une ALTER TABLErequête il y a quelques heures et nous avons récemment réalisé (via pg_stat_activity) qu'elle attendait un verrou. Nous avons découvert l'autre requête qui contient un verrou sur la table que nous voulons modifier et ne pas le laisser partir.

Notre requête est une requête "simple" (modification d'un type de données de colonne), mais elle s'exécute sur une table massive.

Plutôt que de tuer le processus qui maintient la serrure, nous avons décidé que nous préférions tuer le ALTER TABLE.

Nous n'avons pas encapsulé le ALTER TABLEdans une transaction.

Pour autant que je sache, le fait que notre requête attend un verrou signifie qu'elle a toujours attendu un verrou et qu'elle n'a rien changé.

Est-ce vrai? Est-il sûr pour nous d'annuler purement et simplement notre ALTER TABLErequête? Ou est-il possible que la requête ait déjà modifié quelque chose et que son annulation laisserait notre base de données dans un état intermédiaire?

PS: Le plan est de l'annuler en utilisant SELECT pg_cancel_backend(pid);. Si c'est une mauvaise idée, faites-le moi savoir.

JMTyler
la source
1
Cela devrait être bien pour annuler la ALTER TABLE. PostgreSQL a un DDL transactionnel, et vous devriez rester dans le même état que si vous n'aviez pas du tout exécuté ALTER TABLE.
Josh Kupershmidt
Donc, lorsque vous dites que PostgreSQL a une DDL de transaction, cela signifie-t-il que toute requête de changement de schéma est essentiellement exécutée à l'intérieur d'une transaction?
JMTyler
1
Dans votre cas, ALTER TABLE est "essentiellement exécuté dans une transaction", car vous avez dit "Nous n'avons pas encapsulé ALTER TABLE dans une transaction". Si vous le souhaitez, vous pouvez écrire BEGIN; ALTER TABLE foo ...; ALTER TABLE bar ...; etc. ; COMMETTRE; - c'est la véritable caractéristique de PostgreSQL ayant DDL transactionnel. Mais pour votre situation immédiate, oui, la ALTER TABLE seule peut être annulée en toute sécurité et sera annulée comme si elle ne s'était jamais produite.
Josh Kupershmidt
Merci beaucoup pour vos réponses rapides! Ce sont de très bonnes informations. Pourriez-vous l'afficher comme réponse afin que je puisse la marquer comme acceptée?
JMTyler

Réponses:

13

Pour autant que je sache, le fait que notre requête attend un verrou signifie qu'elle a toujours attendu un verrou et qu'elle n'a rien changé.

Droite - si vous voyez que pg_stat_activity.waiting est "vrai" pour une ALTER TABLE, cela signifie presque certainement qu'il attend patiemment le verrou ACCESS EXCLUSIVE sur sa table cible et son vrai travail (réécriture de la table si nécessaire, changement de catalogues , reconstruction d'index, etc.) n'a pas encore commencé.

Est-il sûr pour nous d'annuler purement et simplement notre requête ALTER TABLE? Ou est-il possible que la requête ait déjà modifié quelque chose et que son annulation laisserait notre base de données dans un état intermédiaire?

L'annulation de requêtes (ou, de manière équivalente, l'annulation d'une transaction) dans PostgreSQL ne présente aucun risque de corruption de base de données qui pourrait vous avoir effrayé dans certaines autres bases de données (par exemple l' avertissement terrifiant au bas de cette page). C'est pourquoi les non-superutilisateurs sont, dans les versions récentes, libres d'utiliser pg_cancel_backend()et pg_terminate_backend()de tuer leurs propres requêtes exécutées dans d'autres backends - ils sont sûrs à utiliser sans s'inquiéter de la corruption de la base de données. Après tout, PostgreSQL doit être prêt à faire face à tout processus interrompu, par exemple SIGKILL du tueur OOM, arrêt du serveur, etc. C'est à cela que sert le journal WAL .

Vous avez peut-être également vu que dans PostgreSQL, il est possible d'exécuter la plupart des commandes DDL imbriquées dans une transaction (multi-instructions), par exemple

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

(génial pour vous assurer que les migrations de schéma se déroulent toutes ensemble ou pas du tout.) Vous avez dit, cependant:

Nous n'avons pas encapsulé le ALTER TABLEdans une transaction.

C'est bien pour une seule commande - à partir des documents ,

PostgreSQL traite en fait chaque instruction SQL comme étant exécutée dans une transaction. Si vous n'émettez pas de commande BEGIN, chaque instruction individuelle est entourée d'un BEGIN implicite et (en cas de succès). Un groupe d'instructions entouré de BEGIN et COMMIT est parfois appelé un bloc de transaction.

Ainsi, l'annulation de cela ALTER TABLE, soit par le biais d' pg_cancel_backend()un Ctrl-C émis à partir de l'invite de contrôle de psql, aura un effet similaire à celui que vous aviez fait

BEGIN;
ALTER TABLE ... ;
ROLLBACK;

(même si, comme vous l'espérez, vous avez pu le voir, l'annulation de ce prix ALTER TABLEpeut sauver la base de données de beaucoup de meulage inutile si vous y allez de ROLLBACKtoute façon.)

Josh Kupershmidt
la source
5

Pour développer la réponse correcte et excellente de Josh:

Est-il sûr pour nous d'annuler purement et simplement notre requête ALTER TABLE?

Oui.

Ce serait sûr même s'il était en train de réécrire la table .

Si vous le vouliez, vous pouvez simplement arrêter l'ensemble du serveur PostgreSQL, ou en fait la machine sur laquelle il fonctionne, le redémarrer, et tout irait bien. DDL dans PostgreSQL est transactionnel et sûr.

Les opérations DDL sont enregistrées via WAL et il est garanti qu'elles peuvent être annulées ou terminées lors de la récupération après un crash ou un abandon.

Craig Ringer
la source
3
Juste une note à propos de "vous pouvez simplement arrêter l'ensemble du serveur PostgreSQL, ou en fait la machine sur laquelle il fonctionne, le redémarrer, et tout irait bien" - tout à fait vrai tant que vous avez un matériel fiable qui ne ment pas sur fsync , wiki.postgresql.org/wiki/Reliable_Writes
Josh Kupershmidt
2
@JoshKupershmidt Bien sûr, mais ce n'est pas spécifique à DDL. Si vous avez des problèmes de synchronisation, vous n'êtes pas en sécurité pour tout .
Craig Ringer