• Aucun résultat trouvé

Verrouillage explicite

Dans le document Administration PostgreSQL (Page 157-160)

Contrˆ ole de concurrence

16.3 Verrouillage explicite

PostgreSQL fournit de nombreux modes de verrous pour contrˆoler les acc`es concurrents aux donn´ees des tables. Ces modes peuvent ˆetre utilis´es pour un verrouillage contrˆol´e par l’application dans des situations o`uMVCC n’a pas le comportement d´esir´e. De plus, la plupart des commandes PostgreSQL acqui`erent automatiquement des verrous avec les modes appropri´es pour s’assurer que les tables r´ef´erenc´ees ne sont pas supprim´ees ou modifi´ees de fa¸con incompatible lors que la

commande s’ex´ecute. (Par exemple, ALTER TABLE ne peut pas ˆetre ex´ecut´e en mˆeme temps que d’autres op´erations sur la mˆeme table.)

Pour examiner une liste des verrous actuels dans un serveur de base de donn´ees, utilisez la vue syst`eme pg locks(Voir section 21.32). Pour plus d’informations sur la surveillance du statut du sous-syst`eme de gestion des verrous, r´ef´erez-vous au chapitre 12.

16.3.1 Verrous au niveau table

La liste ci-dessous affiche les modes de verrous disponibles et les contextes dans lesquels ils sont automatiquement utilis´es par PostgreSQL. Rappellez-vous que tous ces modes de verrous sont des verrous au niveau table, mˆeme si le nom contient le mot«row»(NdT : ligne) ; les noms des modes de verrous sont historiques. `A un certain point, les noms refl`etent l’utilisation typique de chaque mode de verrou — mais la s´emantique est identique. La seule vraie diff´erence entre un mode verrou et un autre est l’ensemble des modes verrous avec lesquels ils rentrent en conflit. Deux transactions ne peuvent pas conserver des verrous de modes en conflit sur la mˆeme table au mˆeme moment. (N´eanmoins, une transaction n’entre jamais en conflit avec elle-mˆeme. Par exemple, il pourrait acqu´erir un verrour ACCESS EXCLUSIVE et acqu´erir plus tard un verrou ACCESS SHARE sur la mˆeme table.) Des modes de verrou sans conflit pourraient ˆetre d´etenus en mˆeme temps par plusieurs transactions. Notez en particulier que certains modes de verrous sont en conflit avec eux-mˆeme (par exemple, un verrou ACCESS EXCLUSIVE ne peut pas ˆetre d´etenu par plus d’une transaction `a la fois) alors que d’autres n’entrent pas en conflit avec eux-mˆeme (par exemple, un verrouACCESS SHAREpeut ˆetre d´etenu par de multiples transactions). Une fois acquis, un verrou est conserv´e jusqu’`a la fin de la transaction.

Modes de verrous au niveau table – ACCESS SHARE

En conflit avec le mode verrouACCESS EXCLUSIVE.

Les commandesSELECTetANALYZEacqui`erent un verrou sur ce mode avec les tables r´ef´eren-c´ees. En g´en´eral, tout requˆete lisant seulement une table et ne la modifiant pas acqu´erera ce mode de verrou.

– ROW SHARE

En conflit avec les modes de verrousEXCLUSIVEet ACCESS EXCLUSIVE.

La commande SELECT FOR UPDATE acquiert un verrou sur ce mode avec la table cible (en plus des verrousACCESS SHAREdes autres tables qui sont r´ef´erenc´ees mais pas s´electionn´ees FOR UPDATE).

– ROW EXCLUSIVE

En conflit avec les modes de verrous SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, et ACCESS EXCLUSIVE.

Les commandes UPDATE, DELETE et INSERTacqui`erent ce mode de verrou sur la table cible (en plus des verrous ACCESS SHARE sur toutes les autres tables r´ef´erenc´ees. En g´en´eral, ce mode de verrouillage sera acquis par toute commande modifiant des donn´ees de la table.

– SHARE UPDATE EXCLUSIVE

En conflit avec les modes de verrous SHARE UPDATE EXCLUSIVE, SHARE, EXCLUSIVE, SHARE ROW EXCLUSIVE et ACCESS EXCLUSIVE. Ce mode prot`ege une table contre les modifications concurrentes de sch´ema et pendant l’ex´ecution de VACUUM.

Acquis parVACUUM(sansFULL).

SHARE

En conflit avec les modes de verrousROW EXCLUSIVE,SHARE UPDATE EXCLUSIVE,SHARE ROW EXCLUSIVE,EXCLUSIVEet ACCESS EXCLUSIVE. Ce mode prot`ege une table contre les modifi-cations de donn´ees concurrentes.

Acquis parCREATE INDEX.

– SHARE ROW EXCLUSIVE

En conflit avec les modes de verrous ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVEet ACCESS EXCLUSIVE.

Ce mode de verrouillage n’est pas automatiquement acquis par une commande PostgreSQL.

– EXCLUSIVE

En conflit avec les modes de verrousROW SHARE,ROW EXCLUSIVE,SHARE UPDATE EXCLUSIVE, SHARE,SHARE ROW EXCLUSIVE,EXCLUSIVEetACCESS EXCLUSIVE. Ce mode autorise

unique-ment les verrousACCESS SHAREconcurrents, c’est-`a-dire lit `a partir de la table et effectue en parall`ele avec une transaction contenant ce mode de verrouillage.

Ce mode de verrouillage n’est pas automatiquement acquis par une commande PostgreSQL.

– ACCESS EXCLUSIVE

Entre en conflit avec tous les modes (ACCESS SHARE, ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE et ACCESS EXCLUSIVE). Ce mode garantie que le d´eteneur est la seule transaction `a acc´eder `a la table de cette fa¸con.

Acquis par les commandesALTER TABLE, DROP TABLE, REINDEX, CLUSTERet VACUUM FULL.

C’est aussi le mode de verrou par d´efaut des instructionsLOCK TABLE qui ne sp´ecifient pas de mode explicitement.

Astuce : Seul un verrouACCESS EXCLUSIVEbloque une instructionSELECT(sansFOR UPDATE).

16.3.2 Verrous au niveau ligne

En plus des verrous au niveau table, il existe des verrous au niveau ligne. Un verrou sur une ligne sp´ecifique est automatiquement acquis lorsque la ligne est mise `a jour (ou supprim´ee ou marqu´ee pour mise `a jour). Le verrou est d´etenu jusqu’`a la fin de la transaction, que ce soit une validation ou une annulation. Les verrous au niveau ligne n’affectent pas les requˆetes de donn´ees ; ils bloquent seulement les modifieurs d’une mˆeme ligne. Pour acqu´erir un verrou au niveau ligne sans modifier r´eellement la ligne, s´electionnez la ligne avecSELECT FOR UPDATE. Notez qu’une fois un verrou au niveau ligne acquis, la transaction pourrait mettre `a jour la ligne plusieurs fois sans peur des conflits.

PostgreSQL ne se rappelle aucune information sur les lignes modifi´ees en m´emoire, pour n’avoir aucune limite sur le nombre de lignes verrouill´ees `a un moment donn´e. N´eanmoins, verrouiller une ligne pourrait causer une ´ecriture disque ; du coup, par exemple, SELECT FOR UPDATE modifiera les lignes s´electionn´ees pour les marquer et cela r´esultera en des ´ecritures disques.

En plus des verrous tables et lignes, les verrous partag´es/exclusifs sur les pages sont utilis´es pour contrˆoler la lecture et l’´ecriture des pages de table dans l’ensemble de tampons partag´ees. Ces verrous sont imm´ediatement relˆach´es une fois la ligne r´ecup´er´ee ou mise `a jour. Les d´eveloppeurs d’application ne sont normalement pas concern´ee avec les verrous au niveau page mais nous le mentionnons pour ˆetre le plus complet possible.

16.3.3 Verrous morts (blocage)

L’utilisation de verrous explicites accroˆıt le risque de verrous morts, o`u deux (voire plus) tran-sactions d´etiennent chacun un verrou que l’autre convoite. Par exemple, si la transaction 1 a acquis un verrou exclusif sur la table A puis essaie d’acquerir un verrou exclusif sur la table B, alors que la transaction 2 de d´ej`a un verrou exclusif sur la table B et souhaite maintenant un verrou exclusif sur la table A, alors aucun des deux ne peut continuer. PostgreSQL d´etecte automatiquement ces situations de blocage et les r´esout en annulant une des transactions impliqu´ees, permettant ainsi `a l’autre de se terminer. (Exactement quelle transaction sera annul´ee est difficile `a pr´evoir mais vous ne devriez pas vous y attacher.)

Notez que les verrous morts peuvent aussi arriver comme r´esultat de verrous de niveau ligne (et du coup, ils peuvent se produire mˆeme si le verrouillage explicite n’est pas utilis´e). Consid´erez le cas dans lequel il existe deux transactions concurrentes modifiant une table. La premi`ere transaction ex´ecute :

UPDATE comptes SET balance = balance + 100.00 WHERE no_compte = 11111;

Elle acquiert un verrou au niveau ligne sur la ligne sp´ecifi´ee par le num´ero de compte (no compte).

Ensuite, la deuxi`eme transaction ex´ecute :

UPDATE comptes SET balance = balance + 100.00 WHERE no_compte = 22222;

UPDATE comptes SET balance = balance - 100.00 WHERE no_compte = 11111;

La premi`ere instruction UPDATE acquiert avec succ`es un verrou au niveau ligne sur la ligne sp´ecifi´ee, donc il r´eussit `a mettre `a jour la ligne. N´eanmoins, la deuxi`eme instruction UPDATE trouve que la ligne qu’il essaie de mettre `a jour a d´ej`a ´et´e mise `a jour, alors il attend la fin de la transaction ayant acquis le verrou. Maintenant, la premi`ere transaction ex´ecute :

UPDATE comptes SET balance = balance - 100.00 WHERE no_compte = 22222;

La premi`ere transaction essaie d’acqu´erir un verrou au niveau ligne sur la ligne sp´ecifi´ee mais ne le peut pas : la deuxi`eme transaction d´etient d´ej`a un verrou. Donc, elle attend la fin de la transaction deux. Du coup, la premi`ere transaction est bloqu´ee par la deuxi`eme et la deuxi`eme est bloqu´ee par la premi`ere : une condition de blocage, un verrou mort. PostgreSQL d´etectera cette situation et annulera une des transactions.

La meilleure d´efense contre les verrous morts est g´en´eralement de les ´eviter en s’assurant que toutes les applications utilisant une base de donn´ees acqui`erent des verrours sur des objets multiples dans un ordre coh´erent. C’est la premi`ere raison de l’exemple pr´ec´edent de verrou mort : si les deux transactions avaient mis `a jour les lignes dans le mˆeme ordre, aucun blocage n’aurait eu lieu.

Vous devriez vous assurer que le premier verrou acquis sur un objet dans une transaction est dans le mode le plus haut qui sera n´ecessaire pour cet objet. S’il n’est pas possible de v´erifier ceci `a l’avance, alors les blocages devront ˆetre g´er´es `a l’ex´ecution en r´e-essayant les transactions annul´ees

`a cause de blocage.

Tant qu’aucune situation de blocage n’est d´etect´ee, une transaction cherchant soit un verrou de niveau table soit un verrou de niveau ligne attendra ind´efiniment que les verrous en conflit soient abandonn´es. Ceci signifie qu’il est parfois une mauvaise id´ee pour les applications de d´etenir des transactions ouvertes sur une longue p´eriode de temps (par exemple en attendant une saisie de l’utilisateur).

16.4 V´ erification de coh´ erence des donn´ ees au niveau de

Dans le document Administration PostgreSQL (Page 157-160)