Le standard SQL d�finit quatre niveaux d'isolation de transaction. Le plus strict est Serializable, qui est d�fini par le standard dans un paragraphe qui d�clare que toute ex�cution concurrente d'un jeu de transactions s�rialisables doit apporter la garantie de produire le m�me effet que l'ex�cution cons�cutive de chacun d'entre eux dans un certain ordre. Les trois autres niveaux sont d�finis en terme de ph�nom�nes, r�sultant de l'int�raction entre les transactions concurrentes, qui ne doivent pas se produire � chaque niveau. Le standard note qu'en raison de la d�finition de Serializable, aucun de ces ph�nom�nes n'est possible � ce niveau. (Cela n'a rien de surprenant -- si l'effet des transactions doit �tre coh�rent avec l'ex�cution cons�cutive de chacune d'entre elles, comment pourriez vous voir un ph�nom�ne caus� par des interactions?).
Les ph�nom�nes qui sont interdits � chaque niveau sont:
Une transaction lit des donn�es �crites par une transaction concurrente non valid�e (dirty read).
Une transaction relit des donn�es qu'elle a lu pr�c�demment et trouve que les donn�es ont �t� modifi�es par une autre transaction (valid�e depuis la lecture initiale) (non repeatable read).
Une transaction r�-ex�cute une requ�te renvoyant un ensemble de lignes satisfaisant une condition de recherche et trouve que l'ensemble des lignes satisfaisant la condition a chang� du fait d'une autre transaction r�cemment valid�e (phantom read).
Les quatre niveaux d'isolation de transaction et les comportements correspondants sont d�crits dans le Tableau 13.1, � Niveaux d'isolation standards des transactions SQL �.
Tableau 13.1. Niveaux d'isolation standards des transactions SQL
Niveau d'isolation | Lecture sale | Lecture non reproductible | Lecture fant�me |
---|---|---|---|
Uncommited Read (en fran�ais, � Lecture de donn�es non valid�es �) | Possible | Possible | Possible |
Commited Read (en fran�ais, � Lecture de donn�es valid�es �) | Impossible | Possible | Possible |
Repeatable Read (en fran�ais, � Lecture r�p�t�e �) | Impossible | Impossible | Possible |
Serializable (en fran�ais, � S�rialisable �) | Impossible | Impossible | Impossible |
Dans PostgreSQL™, vous pouvez demander un des quatre niveaux standards d'isolation de transaction. Mais, en interne, il existe seulement trois niveaux distincts d'isolation, qui correspondent aux niveaux Read Committed et Repeatable Read, and Serializable. Lorsque vous s�lectionnez le niveau Read Uncommitted, vous obtenez r�ellement Read Committed, et les lectures fant�mes ne sont pas possibles dans l'impl�mentation PostgreSQL™ de Repeatable Read. Le niveau d'isolation actuel pourrait donc �tre plus strict que ce que vous s�lectionnez. Ceci est permis par le standard SQL. Les quatre niveaux d'isolation d�finissent seulement quel ph�nom�ne ne doit pas survenir, ils ne d�finissent pas ce qui doit arriver. La raison pour laquelle PostgreSQL™ fournit seulement trois niveaux d'isolation est qu'il s'agit de la seule fa�on raisonnable de faire correspondre les niveaux d'isolation standards avec l'architecture de contr�le des acc�s simultan�s multiversion. Le comportement des niveaux standards d'isolation est d�taill� dans les sous-sections suivantes.
Pour initialiser le niveau d'isolation d'une transaction, utilisez la commande SET TRANSACTION(7).
Read Committed est le niveau d'isolation par d�faut dans PostgreSQL™. Quand une transaction utilise ce niveau d'isolation, une requ�te SELECT (sans clause FOR UPDATE/SHARE) voit seulement les donn�es valid�es avant le d�but de la requ�te ; il ne voit jamais les donn�es non valid�es et les modifications valid�es pendant l'ex�cution de la requ�te par des transactions ex�cut�es en parall�le. En effet, une requ�te SELECT voit une image de la base de donn�es datant du moment o� l'ex�cution de la requ�te commence. N�anmoins, SELECT voit les effets de mises � jour pr�c�dentes ex�cut�es dans sa propre transaction, m�me si celles-ci n'ont pas encore �t� valid�es. De plus, notez que deux commandes SELECT successives peuvent voir des donn�es diff�rentes, m�me si elles sont ex�cut�es dans la m�me transaction si d'autres transactions valident des modifications pendant l'ex�cution du premier SELECT.
Les commandes UPDATE, DELETE, SELECT FOR UPDATE et SELECT FOR SHARE se comportent de la m�me fa�on que SELECT en ce qui concerne la recherche des lignes cibles : elles ne trouveront que les lignes cibles qui ont �t� valid�es avant le d�but de la commande. N�anmoins, une telle ligne cible pourrait avoir d�j� �t� mise � jour (ou supprim�e ou verrouill�e) par une autre transaction concurrente au moment o� elle est d�couverte. Dans ce cas, le processus de mise � jour attendra que la premi�re transaction soit valid�e ou annul�e (si elle est toujours en cours). Si la premi�re mise � jour est annul�e, alors ses effets sont ni�s et le deuxi�me processus peut ex�cuter la mise � jour des lignes originellement trouv�es. Si la premi�re mise � jour est valid�e, la deuxi�me mise � jour ignorera la ligne si la premi�re mise � jour l'a supprim�e, sinon elle essaiera d'appliquer son op�ration � la version mise � jour de la ligne. La condition de la recherche de la commande (la clause WHERE) est r�-�valu�e pour savoir si la version mise � jour de la ligne correspond toujours � la condition de recherche. Dans ce cas, la deuxi�me mise � jour continue son op�ration en utilisant la version mise � jour de la ligne. Dans le cas des commandes SELECT FOR UPDATE et SELECT FOR SHARE, cela signifie que la version mise � jour de la ligne est verrouill�e et renvoy�e au client.
À cause de la r�gle ci-dessus, une commande de mise � jour a la possibilit� de voir une image non coh�rente : elle peut voir les effets de commandes de mises � jour concurrentes sur les m�mes lignes que celles qu'elle essaie de mettre � jour mais elle ne voit pas les effets de ces commandes sur les autres lignes de la base de donn�es. Ce comportement rend le mode de lecture valid�e non convenable pour les commandes qui impliquent des conditions de recherche complexes ; n�anmoins, il est int�ressant pour les cas simples. Par exemple, consid�rons la mise � jour de balances de banque avec des transactions comme :
BEGIN; UPDATE comptes SET balance = balance + 100.00 WHERE no_compte = 12345; UPDATE comptes SET balance = balance - 100.00 WHERE no_compte = 7534; COMMIT;
Si deux transactions comme celle-ci essaient de modifier en m�me temps la balance du compte 12345, nous voulons clairement que la deuxi�me transaction commence � partir de la version mise � jour de la ligne du compte. Comme chaque commande n'affecte qu'une ligne pr�d�termin�e, la laisser voir la version mise � jour de la ligne ne cr�e pas de soucis de coh�rence.
Des utilisations plus complexes peuvent produire des r�sultats non d�sir�s dans le mode Read Committed. Par exemple, consid�rez une commande DELETE op�rant sur des donn�es qui sont � la fois ajout�es et supprim�es du crit�re de restriction par une autre commande. Supposons que website est une table sur deux lignes avec website.hits valant 9 et 10 :
BEGIN; UPDATE website SET hits = hits + 1; -- ex�cut� par une autre session : DELETE FROM website WHERE hits = 10; COMMIT;
La commande DELETE n'aura pas d'effet m�me s'il existe une ligne website.hits = 10 avant et apr�s la commande UPDATE. Cela survient parce que la valeur 9 de la ligne avant mise � jour est ignor�e et que lorsque l'UPDATE termine et que DELETE obtient un verrou, la nouvelle valeur de la ligne n'est plus 10, mais 11, ce qui ne correspond plus au crit�re.
Comme le mode Read Committed commence chaque commande avec une nouvelle image qui inclut toutes les transactions valid�es jusqu'� cet instant, les commandes suivantes dans la m�me transaction verront les effets de la transaction valid�e en parall�le dans tous les cas. Le probl�me en question est de savoir si une seule commande voit une vue absolument coh�rente ou non de la base de donn�es.
L'isolation partielle des transactions fournie par le mode Read Committed est ad�quate pour de nombreuses applications, et ce mode est rapide et simple � utiliser. N�anmoins, il n'est pas suffisant dans tous les cas. Les applications qui ex�cutent des requ�tes et des mises � jour complexes pourraient avoir besoin d'une vue plus rigoureusement coh�rente de la base de donn�es, une vue que le mode Read Committed ne fournit pas.
Le niveau d'isolation Repeatable Read ne voit que les donn�es valid�es avant que la transaction ait d�marr�; il ne voit jamais ni les donn�es non valid�es, ni les donn�es valid�es par des transactions concurrentes durant son ex�cution. (Toutefois, la requ�te voit les effets de mises � jour pr�c�dentes effectu�es dans sa propre transaction, bien qu'elles ne soient pas encore valid�es). C'est une garantie plus �lev�e que requise par le standard SQL pour ce niveau d'isolation, et elle �vite le ph�nom�ne d�crit dans Tableau 13.1, � Niveaux d'isolation standards des transactions SQL �. Comme mentionn� plus haut, c'est permis par le standard, qui ne d�finit que la protection minimale que chaque niveau d'isolation doit fournir.
Ce niveau est diff�rent de Read Committed parce qu'une requ�te dans une transaction repeatable read voit un instantan� au d�but de la transaction, et non pas du d�but de la requ�te en cours � l'int�rieur de la transaction. Du coup, les commandes SELECT successives � l'int�rieur d'une seule transaction voient toujours les m�mes donn�es, c'est-�-dire qu'elles ne voient jamais les modifications faites par les autres transactions qui ont valid� apr�s le d�but de leur propre transaction.
Les applications utilisant ce niveau d'isolation doivent �tre pr�par�es � retenter des transactions � cause d'�checs de s�rialisation.
Les commandes UPDATE, DELETE, SELECT FOR UPDATE et SELECT FOR SHARE se comportent de la m�me fa�on que SELECT en ce qui concerne la recherche de lignes cibles : elles trouveront seulement les lignes cibles qui ont �t� valid�es avant le d�but de la transaction. N�anmoins, une telle ligne cible pourrait avoir �t� mise � jour (ou supprim�e ou verrouill�e) par une autre transaction concurrente au moment o� elle est utilis�e. Dans ce cas, la transaction repeatable read attendra que la premi�re transaction de mise � jour soit valid�e ou annul�e (si celle-ci est toujours en cours). Si la premi�re mise � jour est annul�e, les effets sont invers�s et la transaction repeatable read peut continuer avec la mise � jour de la ligne trouv�e � l'origine. Mais si la mise � jour est valid�e (et que la ligne est mise � jour ou supprim�e, pas simplement verrouill�e), alors la transaction repeatable read sera annul�e avec le message
ERROR: could not serialize access due to concurrent update
parce qu'une transaction s�rialisable ne peut pas modifier ou verrouiller les lignes chang�es par d'autres transactions apr�s que la transaction s�rialisable ait commenc�.
Quand une application re�oit ce message d'erreurs, elle devrait annuler la transaction actuelle et r�-essayer la transaction compl�te. La seconde fois, la transaction voit les modifications d�j� valid�es comme faisant partie de sa vue initiale de la base de donn�es, donc il n'y a pas de conflit logique en utilisant la nouvelle version de la ligne comme point de d�part pour la mise � jour de la nouvelle transaction.
Notez que seules les transactions de modifications ont besoin d'�tre tent�es de nouveau ; les transactions en lecture seule n'auront jamais de conflits de s�rialisation.
Le mode Repeatable Repeatable fournit une garantie rigoureuse que chaque transaction voit un �tat compl�tement stable de la base de donn�es. Toutefois cette vue ne sera pas n�cessairement toujours coh�rente avec l'ex�cution s�rielle (un � la fois) de transactions concurrentes du m�me niveau d'isolation. Par exemple, m�me une transaction en lecture seule � ce niveau pourrait voire un enregistrement de contr�le mis � jour pour indiquer qu'un traitement par lot a �t� termin� mais ne pas voir un des enregistrements de d�tail qui est une partie logique du traitement par lot parce qu'il a lu une ancienne version de l'enregistrement de contr�le. L'impl�mentation correcte de r�gles de gestion par des transactions s'ex�cutant � ce niveau d'isolation risque de ne pas marcher correctement sans une utilisation prudente de verrouillages explicites qui bloquent les transactions en conflits.
Avant la version 9.1 de PostgreSQL™, une demande d'isolation de transaction Serializable fournissait exactement le comportement d�crit ici. Pour maintenir l'ancien niveau Serializable, il faudra maintenant demander Repeatable Read.
Le niveau d'isolation Serializable fournit le niveau d'isolation le plus strict. Ce niveau �mule l'ex�cution s�rielle de transaction, comme si les transactions avaient �t� ex�cut�es les unes apr�s les autres, s�quentiellement, plut�t que simultan�ment. Toutefois, comme pour le niveau Repeatable Read, les applications utilisant ce niveau d'isolation doivent �tre pr�tes � r�p�ter leurs transactions en cas d'�chec de s�rialisation. En fait, ce niveau d'isolation fonctionne exactement comme Repeatable Read, except� qu'il surveille les conditions qui pourraient amener l'ex�cution d'un jeu de transactions concurrentes � se comporter d'une mani�re incomptible avec les ex�cutions s�rielles (une � la fois) de toutes ces transactions. Cette surveillance n'introduit aucun blocage suppl�mentaire par rapport � repeatable read, mais il y a un co�t � cette surveillance, et la d�tection des conditions pouvant amener une anomalie de s�rialisation d�clenchera un �chec de s�rialisation.
Comme exemple, consid�rez la table ma_table, contenant initialement
classe | valeur --------+------- 1 | 10 1 | 20 2 | 100 2 | 200
Supposons que la transaction s�rialisable A traite
SELECT SUM(valeur) FROM ma_table WHERE classe = 1;
puis ins�re le r�sultat (30) comme valeur dans une nouvelle ligne avec classe = 2. Simultan�ment, la transaction serialisable B traite
SELECT SUM(valeur) FROM ma_table WHERE classe = 2;
et obtient le r�sultat 300, qu'il ins�re dans une nouvelle ligne avec classe = 1. À ce moment l� les deux transactions essayent de valider. Si l'une des transactions fonctionnait au niveau d'isolation Repeatable Read, les deux seraient autoris�es � valider; mais puisqu'il n'y a pas d'ordre d'ex�cution s�riel coh�rent avec le r�sultat, l'utilisation de transactions Serializable permettra � une des deux transactions de valider, et annulera l'autre avec ce message:
ERREUR: n'a pas pu s�rialiser un acc�s � cause d'une mise � jour en parall�le"
C'est parce que si A a �t� ex�cut� avant B, B aurait trouv� la somme 330, et non pas 300. De fa�on similaire, l'autre ordre aurait eu comme r�sultat une somme diff�rente pour le calcul par A.
Pour garantir une vraie s�rialisation PostgreSQL™ utilise le verrouillage de pr�dicats, ce qui signifie qu'il conserve des verrous qui permettent de d�terminer quand une �criture aurait eu un impact sur le r�sultat d'une lecture ant�rieure par une transaction concurrente, si elle s'�tait ex�cut�e d'abord. Dans PostgreSQL™, ces verrous ne causent pas de blocage et ne peuvent donc pas jouer un r�le dans l'av�nement d'un verrou mortel (deadlock). Ils sont utilis�s pour identifier et marquer les d�pendances entre des transactions s�rialisables concurrentes qui dans certaines combinaisons peuvent entrainer des anomalies de s�rialisation. Par contraste, une transaction Read Committed ou Repeatable Read qui voudrait garantir la coh�rence des donn�es devra prendre un verrou sur la table enti�re, ce qui pourrait bloquer d'autres utilisateurs voulant utiliser cette table, ou pourrait utiliser SELECT FOR UPDATE ou SELECT FOR SELECT qui non seulement peut bloquer d'autres transactions, mais entra�ne un acc�s au disque.
Les verrous de pr�dicats dans PostgreSQL™, comme dans la plupart des autres syst�mes de bases de donn�es, s'appuient sur les donn�es r�ellement acc�d�es par une transaction. Ils seront visibles dans la vue syst�me pg_locks avec un mode de SIReadLock. Les verrous acquis pendant l'ex�cution d'une requ�te d�pendront du plan utilis� par la requ�te, et plusieurs verrous fins (par exemple, des verrous d'enregistrement) pourraient �tre combin�s en verrous plus grossiers (par exemple, des verrous de page) pendant le d�roulement de la transaction afin d'�viter d'�puiser la m�moire utilis�e pour suivre les verrous. Une transaction READ ONLY pourra lib�rer ses verrous SIRead avant sa fin, si elle d�tecte qu'aucun conflit ne peut encore se produire pouvant potentiellement entrainer une anomalie de s�rialisation. En fait, les transaction READ ONLY seront souvent capable d'�tablir ce fait au moment de leur d�marrage, et ainsi �viter de prendre des verrous de pr�dicat. Si vous demandez explicitement une transaction SERIALIZABLE READ ONLY DEFERRABLE, elle bloquera jusqu'� ce qu'elle puisse �tablir ce fait. (C'est le seul cas o�_une transaction Serializable bloque mais pas une transaction Repeatable Read.) D'autre part, les verrous SIRead doivent souvent �tre gard�s apr�s la fin d'une transaction, jusqu'� ce que toutes les lectures-�critures s'�tant d�roul�es simultan�ment soient termin�es.
L'utilisation syst�matique de transactions Serializable peut simplifier le d�veloppement. La garantie que n'importe quel jeu de transactions concurrentes aura le m�me effet que si elles s'ex�cutent une seule � la fois signifie que si vous pouvez d�montrer qu'une transaction seule, comme elle est �crite, effectuera ce qui est attendu quand elle est ex�cut�e seule, vous pouvez �tre s�r qu'elle effectuera ce qui est attendu quelques soient les autres transactions serializable qui s'ex�cutent en m�me temps, m�me sans aucune information sur ce que ces autres transactions pourraient faire. Il est important qu'un environnement qui utilise cette technique ait une fa�on g�n�ralis�e de traiter les erreurs de s�rialisation (qui retournent toujours un SQLSTATE valant '40001'), parce qu'il sera tr�s difficile de pr�dire exactement quelles transactions pourraient contribuer � des d�pendances lecture/�criture et auront besoin d'�tre annul�es pour �viter les anomalies de s�rialisation. La surveillance des d�pendances lecture/�criture a un co�t, tout comme l'�chec, mais mis en face du co�t et du blocage entrain�s par les verrous explicites et SELECT FOR UPDATE ou SELECT FOR SHARE, les transactions serializable sont le meilleur choix en termes de performances pour certains environnements.
Pour une performance optimale quand on s'appuie sur les transactions Serializable pour le contr�le de la concurrence, ces points doivent �tre pris en consid�ration:
D�clarer les transactions comme READ ONLY quand c'est possible.
Contr�ler le nombre de connexions actives, en utilisant un pool de connexions si n�cessaire. C'est toujours un point important pour les performances, mais cela peut �tre particuli�rement important pour un syst�me charg� qui utilise des transactions Serializable.
Ne mettez jamais plus dans une transaction seule qu'il n'est n�cessaire dans un but d'int�grit�.
Ne laissez pas des connexions trainer en � idle in transaction � plus longtemps que n�cessaire.
Supprimez les verrous explicites, SELECT FOR UPDATE, et SELECT FOR SHARE qui ne sont plus n�cessaires gr�ce aux protections fournies automatiquement par les transactions Serializable.
Quand le syst�me est forc� � combiner plusieurs verrous de pr�dicat au niveau page en un seul verrou de pr�dicat au niveau relation (si la table des verrous de pr�dicat est � court de m�moire), une augmentation du taux d'�checs de s�rialisation peut survenir. Vous pouvez �viter ceci en augmentant max_pred_locks_per_transaction.
Un parcours s�quentiel n�cessitera toujours un verrou de pr�dicat au niveau relation. Ceci peut r�sulter en un taux plus important d'�checs de s�rialisation. Il peut �tre utile d'encourager l'utilisation de parcours d'index en diminuant random_page_cost et/ou en augmentant cpu_tuple_cost. Assurez-vous de bien mesurer toute diminution du nombre d'annulation de transactions et restarts against any overall change in query execution time.
Le support pour le niveau d'isolation Serializable n'a pas encore �t� ajout� aux cibles de r�plication Hot Standby (d�crites dans Section 25.5, � Hot Standby �). Bien que les �critures permanentes dans la base effectu�es dans des transactions Serializable sur le ma�tre garantiront que toutes les standbys atteindront un �tat coh�rent, une transaction Repeatable Read sur la standby pourra quelquefois voir un �tat transitoire qui sera incoh�rent avec une ex�cution s�rielle sur le ma�tre.