PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Éviter les verrous d'accès exclusifs sur les tables référencées lors du DROPping dans PostgreSQL

Pour tous ceux qui recherchent sur Google et essaient de comprendre pourquoi leur table de dépôt (ou leur clé étrangère ou leur ajout de clé étrangère) est restée bloquée pendant longtemps :

PostgreSQL (J'ai regardé les versions 9.4 à 13) les contraintes de clé étrangère sont en fait implémentées à l'aide de déclencheurs aux deux extrémités de la clé étrangère .

Si vous avez une table company (id comme clé primaire) et une table bank_account (id comme clé primaire, company_id comme clé étrangère pointant vers company.id), alors il y a en fait 2 déclencheurs sur la table bank_account et aussi 2 déclencheurs sur la société tableau.

table_name délai nom_déclencheur nom_fonction
bank_account APRÈS LA MISE À JOUR RI_ConstraintTrigger_c_1515961 RI_FKey_check_upd
compte_bancaire APRÈS INSÉRER RI_ConstraintTrigger_c_1515960 RI_FKey_check_ins
entreprise APRÈS LA MISE À JOUR RI_ConstraintTrigger_a_1515959 RI_FKey_noaction_upd
entreprise APRÈS SUPPRESSION RI_ConstraintTrigger_a_1515958 RI_FKey_noaction_del

La création initiale de ces déclencheurs (lors de la création de la clé foreing) nécessite un verrou SHARE ROW EXCLUSIVE sur ces tables (il s'agissait auparavant du verrou ACCESS EXCLUSIVE dans la version 9.4 et les versions antérieures). Ce verrou n'entre pas en conflit avec les "verrous de lecture de données", mais entrera en conflit avec tous les autres verrous, par exemple un simple INSERT/UPDATE/DELETE dans la table de l'entreprise.

La suppression de ces déclencheurs (lors de la suppression de la clé étrangère ou de la table entière) nécessite un verrou ACCESS EXCLUSIVE sur ces tables. Ce verrou est en conflit avec tous les autres verrous !

Imaginez donc un scénario dans lequel vous avez une transaction A en cours d'exécution qui a d'abord effectué un simple SELECT à partir de la table de l'entreprise (l'amenant à maintenir un verrou ACCESS SHARE pour la table de l'entreprise jusqu'à ce que la transaction soit validée ou annulée) et effectue maintenant un autre travail pour 3 minutes. Vous essayez de supprimer la table bank_account dans la transaction B. Cela nécessite le verrou ACCESS EXCLUSIVE, qui devra attendre que le verrou ACCESS SHARE soit d'abord libéré. ou peut-être INSERT/UPDATE/DELETE), sera mis en file d'attente pour attendre le verrou ACCESS EXCLUSIVE, qui attend le verrou ACCESS SHARE.

Les transactions de longue durée et les modifications DDL nécessitent une manipulation délicate.