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

Erreur de blocage dans l'instruction INSERT

Une façon de gérer les interblocages consiste à disposer d'un mécanisme de nouvelle tentative qui attend un intervalle aléatoire et tente d'exécuter à nouveau la transaction. L'intervalle aléatoire est nécessaire pour que les transactions en collision ne se heurtent pas continuellement, provoquant ce qu'on appelle un verrouillage en direct - quelque chose d'encore plus désagréable à déboguer. En fait, la plupart des applications complexes auront tôt ou tard besoin d'un tel mécanisme de nouvelle tentative lorsqu'elles devront gérer les échecs de sérialisation des transactions.

Bien sûr, si vous êtes en mesure de déterminer la cause du blocage, il est généralement préférable de l'éliminer, sinon il le fera reviens te mordre. Dans presque tous les cas, même lorsque la condition de blocage est rare, le peu de débit et de surcharge de codage pour obtenir les verrous dans un ordre déterministe ou obtenir des verrous plus grossiers en vaut la peine pour éviter les temps de latence importants et la falaise soudaine des performances. lors de la mise à l'échelle de la simultanéité.

Lorsque vous obtenez constamment deux instructions INSERT interbloquantes, il s'agit probablement d'un problème d'ordre d'insertion d'index unique. Essayez par exemple ce qui suit dans deux fenêtres de commande psql :

Thread A           | Thread B
BEGIN;             | BEGIN;
                   | INSERT uniq=1;
INSERT uniq=2;     | 
                   | INSERT uniq=2; 
                   |   block waiting for thread A to commit or rollback, to
                   |   see if this is an unique key error.
INSERT uniq=1;     |
   blocks waiting  |
   for thread B,   |
     DEADLOCK      | 
                   V    

Habituellement, le meilleur plan d'action pour résoudre ce problème consiste à déterminer les objets parents qui protègent toutes ces transactions. La plupart des applications ont une ou deux entités principales, telles que des utilisateurs ou des comptes, qui sont de bons candidats pour cela. Ensuite, tout ce dont vous avez besoin est que chaque transaction obtienne les verrous sur l'entité principale qu'elle touche via SELECT ... FOR UPDATE. Ou si vous en touchez plusieurs, obtenez des verrous sur chacun d'eux mais dans le même ordre à chaque fois (l'ordre par clé primaire est un bon choix).