PostgreSQL est livré avec des fonctionnalités solides et éprouvées qui vous permettent de définir exactement ce qui doit se passer lorsque plusieurs clients tentent de mettre à jour les mêmes données simultanément. L'une d'entre elles est le niveau d'isolement des transactions.
Lisez la suite pour en savoir plus sur le fonctionnement de l'isolation des transactions dans PostgreSQL.
Transactions et niveau d'isolement
Les transactions sont le moyen fondamental de muter des données dans un SGBDR. Les SGBDR modernes permettent à plusieurs transactions de s'exécuter simultanément et, par conséquent, sont livrés avec une variété d'outils - certains standard, d'autres spécifiques au SGBDR - permettant aux développeurs d'applications de spécifier comment leurs transactions doivent ou ne doivent pas interagir avec d'autres transactions.
Les niveaux d'isolation des transactions et les verrous pessimistes sont deux de ces outils. Bien qu'ils soient nécessaires à l'intégrité et aux performances des données, ils ne sont malheureusement pas intuitifs à comprendre ou à utiliser.
Le niveau d'isolement d'une transaction, dans PostgreSQL, peut être l'un des suivants :
- Lire validé
- Lecture répétable
- Sérialisable
Chaque transaction a son niveau d'isolement défini sur l'un de ceux-ci lors de sa création. Le niveau par défaut est « lecture validée ».
Notez que le standard SQL définit également "read uncommitted", qui n'est pas pris en charge dans Postgres. Vous devez utiliser le niveau le plus proche et le plus élevé de "lecture validée".
Voyons ce que signifient ces niveaux.
Lire validé
Que se passe-t-il lorsqu'une transaction (inachevée) insère des lignes dans une table et que l'autre transaction (également inachevée) essaie de lire toutes les lignes de la table ? Si la deuxième transaction est capable de voir les lignes insérées par la première, alors cette lecture est appelée une lecture sale – car la première transaction peut être annulée et la deuxième transaction aurait lu des lignes "fantômes" qui n'ont jamais existé.
La lecture validée le niveau d'isolement garantit que les lectures incorrectes ne se produiront jamais. Voici un exemple :
Comme vous pouvez le voir, la deuxième transaction n'a pas pu lire les données non encore validées de la première transaction. Dans PostgreSQL, il n'est pas possible d'abaisser le niveau d'isolement en dessous de ce niveau afin que les lectures incorrectes soient autorisées.
Lecture répétable
Un autre problème encore est celui des lectures non répétables. Cela se produit lorsqu'une transaction lit une ligne, puis la relit un peu plus tard, mais obtient un résultat différent, car la ligne a été mise à jour entre-temps par une autre transaction. La lecture est devenue non répétable , comme illustré dans cet exemple :
Pour résoudre ce problème, définissez le niveau d'isolement de la transaction sur "repeatableread". PostgreSQL s'assurera alors que la deuxième lecture (ou n'importe laquelle) renverra également le même résultat que la première lecture. Voici le même scénario au niveau d'isolement amélioré :
Notez que le niveau d'isolement a été spécifié avec l'instruction BEGIN. Il est également possible de le spécifier au niveau de la connexion (en tant que paramètre de connexion), en tant que paramètre de configuration (default_transaction_isolation
) et en utilisant l'instruction SET TRANSACTION.
Sérialisable
Le niveau d'isolement suivant résout le problème des mises à jour perdues . Les mises à jour effectuées dans une transaction peuvent être « perdues » ou écrasées par une autre transaction exécutée simultanément, comme illustré ici :
Ici, les blocs UPDATE de la deuxième transaction, car PostgreSQL place un verrou pour empêcher une autre mise à jour jusqu'à ce que la première transaction soit terminée. Cependant, la modification de la première transaction est perdue, car la seconde a "écrasé" la ligne.
Si ce type de comportement n'est pas acceptable, vous pouvez mettre à niveau le niveau d'isolement en sérialisable :
À ce niveau, la validation de la deuxième transaction échoue. Les actions de la deuxième transaction étaient basées sur des faits rendus invalides au moment où elle était sur le point de se commettre.
Bien que la sérialisation offre le plus haut niveau de sécurité, cela signifie également que l'application doit détecter ces échecs de validation et réessayer l'intégralité de la transaction.