L'un des avantages de PostgreSQL™ et de son contrôle d'accès simultané (« Multi-Version Concurrency Control », nommé MVCC par la suite) est qu'il élimine de nombreuses raisons de verrouiller les objets de base de données. Sur certains systèmes de gestion de bases de données, vous devez verrouiller une table lorsque vous souhaitez insérer des données dans celle-ci ; cela peut gêner sévèrement les performances. Sur d'autres systèmes, les lectures bloquent les écritures concurrentes. Avec MVCC, PostgreSQL™ supprime toute une catégorie de verrous, dans le sens où les « vieilles lectures » peuvent accéder aux « anciennes lignes ». La plupart du temps, cela évite aux utilisateurs de PostgreSQL™ de trop se préoccuper des verrous. Les événements de configuration de Slony-I™ récupèrent habituellement des verrous sur une table interne, sl_config_lock, qui ne devrait pas être visible pour les applications à moins que ces dernières doivent exécuter des actions sur les composants Slony-I™.
Malheureusement, il existe plusieurs sortes d'événements Slony-I™ qui nécessitent des verrous exclusifs sur les tables PostgreSQL™, ce qui entraine que la modification de la configuration Slony-I™ peut provoquer des « verrous gênants ». En particulier :
Un verrou exclusif et momentané doit être posé sur une table du nœud « origine » afin d'ajouter le trigger qui collecte les mises à jour de cette table. Il doit simplement être posé assez longtemps pour établir le nouveau trigger.
Lorsqu'un ensemble sur un nœud origine est déplacé vers un autre nœud, des verrous exclusifs sont posés sur chaque table répliquée à la fois sur l'ancien et le nouveau nœud origine afin de modifier les triggers sur ces tables.
Cette opération demande explicitement des verrous sur chaque table dans un ensemble de réplication donné sur le nœud origine.
Cette opération lance un ensemble de requêtes SQL ; pour qu'elle fonctionne, les triggers Slony-I™ doivent être retirés, ensuite les requêtes sont exécutées (ce qui peut modifier les données), enfin les triggers sont restaurés. Pour cela, l'opération doit acquérir des verrous sur toutes les tables de chaque nœud.
Pendant un événement SUBSCRIBE_SET sur un nouvel abonné
Dans un sens, c'est le scénario le moins perturbant car, avant que l'ensemble de réplication soit complet, on peut penser que le nœud « inutilisable » et que Slony-I™ peut raisonnablement demander l'accès exclusif sur le nœud.
Un changement dans la version 1.2 provoque une requête SQL LOCK TABLE explicite qui est placée dans la boucle qui valide que toutes les tables sont présentes. Cela signifie que toutes les tables de l'ensemble de réplication sont verrouillées avec un verrou exclusif pour la durée totale du processus de souscription. En verrouillant les tables très tôt, on s'assure que la souscription n'échouera pas à cause d'un autre processus ayant un verrou sur une table.
Dans tous les cas, notez que ce script opère « sur un nouveau nœud abonné ». Les verrous sont posés « sur un nouveau nœud abonné ». Ils ne s'appliquent pas au nœud fournisseur ou au nœud origine.
pg_autovacuum ne fait pas partie de Slony-I™ mais il se réveille une fois par minute et peut, à tout moment, se lancer dans le nettoyage d'une table, et ainsi poser un verrou ShareUpdateExclusiveLock. Ceci peut bloquer les autres événements pendant une période imprévisible.
Chacune de ces actions nécessite, à un certain de point, de modifier chaque table de l'ensemble de réplication, ce qui implique l'acquisition d'un verrou exclusif sur les tables. Certains utilisateurs ont tenté d'effectuer ces opérations sur des nœuds qui étaient activement sollicités par la couche applicative ; ils ont rencontré des problèmes d'inter-blocages (« deadlocks ») et/ou des arrêts de réplication.
La question évident est : « que faire pour éviter ces inter-blocages ? »
Plusieurs possibilités sont envisageables :
Annoncer une coupure de service pour éviter les inter-blocages.
Si vous pouvez empêcher temporairement les applications d'accéder à la base de données, cela vous offrira une fenêtre de temps pendant laquelle aucune opération ne sera effectuée sur la base de données, à l'exception des processus d'administration que vous controllerez.
Tenter l'operation, en espérant que cela fonctionne.
Puisque rien n'empêche les application de laisser des verrous sur votre chemin, vous pourrez vous retrouver dans une situation de blocage. Mais si le nombre de verrous restant est faible, vous pouvez négocier avec les utilisateurs pour « avoir la priorité ».
Utiliser pgpool.
Si vous pouvez utiliser pgpool ou un « gestionnaire de connexions » similaire, vous pouvez configurer le programme pour qu'il n'utilise plus la base pendant un petit moment, et ainsi le laisser « bloquer » les applications pour vous. L'idéal étant que le gestionnaire de connexions retienne les requêtes assez longtemps pour que la coupure de service apparaisse comme un simple ralentissement.
Gestion rapide de coupure de service.
La procédure suivante minimisera le temps de coupure de service :
Modifier pg_hba.conf afin que seul l'utilisateur slony ait accès à la base de données.
Envoyer un kill -SIGHUP au postmaster de PostgreSQL™.
Ceci ne tuera pas les longues requêtes qui pourraient être en cours d'exécution mais cela empêchera les nouvelles d'entrer. Cela a un impact sur l'application puisque les requêtes entrantes seront rejetées jusqu'à la fin de la procédure.
Si « tout va bien », alors on peut effectuer sans danger l'opération Slony-I™.
Si une requête est toujours en cours, vous devrez peut-être effectuer un kill -SIGQUIT sur un des processus PostgreSQL™. Cela relancera le moteur et tuera toutes les requêtes en attente. Vous devrez probablement relancer les processus slon(1) qui sont attachés à ce nœud.
À ce point, l'opération Slony-I™ peut être effectuée sans danger ; il n'y aura aucun autre processus concurrent.
Recharger l'ancienne version du fichier pg_hba.conf pour autoriser les utilisateurs, et envoyer un kill -SIGHUP au processus postmaster pour qu'il recharge la configuration de sécurité.
La section Section 17, « Changements du schéma de la base (DDL) » suggère des techniques supplémentaires qui peuvent être utiles, telles que le déplacement des tables vers d'autres ensemble de réplication afin de minimiser le nombre de tables qu'il faut verrouiller.
Malheureusement, il n'y a pas de solution miracle. S'il est nécessaire de soumettre une requête SLONIK MOVE SET(7), alors il est probablement nécessaire d'accepter une courte coupure de service. Au fur et à mesure que les relations entre Slony-I™ et pgpool s'améliorent, ce couple semble être la meilleure méthode pour éviter les inter-blocages.