LOCK — verrouiller une table
LOCK [ TABLE ] [ ONLY ]nom
[ * ] [, ...] [ INmode_verrou
MODE ] [ NOWAIT ] oùmode_verrou
peut être : ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE
LOCK TABLE
prend un verrou de niveau table, attendant
si nécessaire que tout verrou conflictuel soit relâché. Si
NOWAIT
est spécifié, LOCK TABLE
n'attend pas l'acquisition du verrou désiré : s'il ne peut pas être
obtenu immédiatement, la commande est annulée et une erreur est émise. Une
fois obtenu, le verrou est conservé jusqu'à la fin de la transaction en cours.
(Il n'y a pas de commande UNLOCK TABLE
; les verrous
sont systématiquement relâchés à la fin de la transaction.)
Quand une vue est verrouillée, toutes les relations apparaissant dans la requête de définition de la vue sont aussi verrouillée récursivement avec le même mode de verrou.
Lors de l'acquisition automatique de verrous pour les commandes qui
référencent des tables, PostgreSQL utilise
toujours le mode de verrou le moins restrictif possible. LOCK
TABLE
est utilisable lorsqu'il est nécessaire d'obtenir des
verrous plus restrictifs.
Soit, par exemple, une application qui exécute
une transaction de niveau d'isolation READ COMMITTED
. Pour
s'assurer que les données de la table sont immuables pendant toute la durée
de la transaction, un verrou SHARE
de niveau table
peut être obtenu avant d'effectuer la requête. Cela empêche toute modification
concurrente des données. Cela assure également que toute lecture intervenant
ensuite sur la table accède à la même vue des données validées. En effet, un
verrou SHARE
entre en conflit avec le verrou
ROW EXCLUSIVE
pris par les modificateurs et l'instruction
LOCK TABLE
attend que tout détenteur concurrent de verrous de mode
nom
IN SHARE MODEROW EXCLUSIVE
valide ou annule. De ce fait, une fois le verrou obtenu,
il ne reste aucune écriture non validée en attente ; de plus, aucune ne peut
commencer tant que le verrou acquis n'est pas relâché.
Pour obtenir un effet similaire lors de l'exécution d'une transaction de
niveau d'isolation REPEATABLE READ
ou SERIALIZABLE
,
il est nécessaire d'exécuter l'instruction
LOCK TABLE
avant toute instruction
SELECT
ou de modification de données. La vue des données
utilisée par une transaction
REPEATABLE READ
or SERIALIZABLE
est figée au moment où débute la
première instruction SELECT
ou de modification des données.
Un LOCK TABLE
ultérieur empêche encore les écritures concurrentes
-- mais il n'assure pas que la transaction lit les dernières données validées.
Si une telle transaction modifie les données de la table,
elle doit utiliser le mode de verrou SHARE ROW EXCLUSIVE
au
lieu du mode SHARE
. Cela assure l'exécution d'une seule
transaction de ce type à la fois. Sans cela, une situation de verrou mort est
possible : deux transactions peuvent acquérir le mode
SHARE
et être ensuite incapables d'acquérir aussi le mode
ROW EXCLUSIVE
pour réellement effectuer leurs mises à jour.
(Les verrous d'une transaction ne sont jamais en conflit. Une
transaction peut de ce fait acquérir le mode ROW EXCLUSIVE
alors qu'elle détient le mode SHARE
-- mais pas si une autre transaction détient le
mode SHARE
.) Pour éviter les verrous bloquants, il est
préférable que toutes les transactions qui acquièrent des verrous sur les
mêmes objets le fassent dans le même ordre. De plus si de multiples modes
de verrous sont impliqués pour un même objet, le verrou de mode le plus
restrictif doit être acquis le premier.
Plus d'informations sur les modes de verrou et les stratégies de verrouillage sont disponibles dans Section 13.3.
nom
Le nom d'une table à verrouiller (éventuellement qualifié du nom du
schéma). Si ONLY
est précisé avant le nom de la table,
seule cette table est verrouillée. Dans le cas contraire, la table et
toutes ses tables filles (si elle en a) sont verrouillées. En option,
*
peut être placé après le nom de la table pour indiquer
explicitement que les tables filles sont inclues.
La commande LOCK a, b;
est équivalente à LOCK a; LOCK
b;
. Les tables sont verrouillées une par une dans l'ordre
précisé par la commande LOCK TABLE
.
modeverrou
Le mode de verrou précise les verrous avec lesquels ce verrou entre en conflit. Les modes de verrou sont décrits dans Section 13.3.
Si aucun mode de verrou n'est précisé,
ACCESS EXCLUSIVE
, mode le plus restrictif, est utilisé.
NOWAIT
LOCK TABLE
n'attend pas que les verrous
conflictuels soient relâchés : si le verrou indiqué ne peut être
acquis immédiatement sans attente, la transaction est annulée.
Pour verrouiller une table, l'utilisateur doit avoir le bon droit pour
le mode_verrou
indiqué.
Si l'utilisateur a les droits MAINTAIN
,
UPDATE
, DELETE
ou
TRUNCATE
sur la table, tout mode_verrou
est autorisé. Si l'utilisateur
a le droit INSERT
sur la table, ROW EXCLUSIVE
MODE
(ou un mode plus fiable comme décrit dans Section 13.3) est autorisé. Si un utilisateur a le droit
SELECT
sur la table, ACCESS SHARE
MODE
est autorisé.
L'utilisateur réalisant un verrou sur la vue doit avoir le droit
correspondant sur la vue. De plus, par défaut, le propriétaire de la vue doit
avoir les droits correspondants sur les relations de base sous-jacentes mais
l'utilisateur réalisant le verrou n'a pas besoin de ces droits. Néanmoins,
si la vue a l'option security_invoker
configurée à
true
(voir CREATE
VIEW
), l'utilisateur réalisant le verrou, plutôt que le
propriétaire de la vue, doit avoir les droits adéquats pour les relations
sous-jacentes.
LOCK TABLE
est inutile à l'extérieur d'un bloc de
transaction : le verrou est détenu jusqu'à la fin de l'instruction.
Du coup, PostgreSQL renvoie une erreur si
LOCK
est utilisé en dehors d'un bloc de transaction.
Utilisez BEGIN
et
COMMIT
(ou ROLLBACK
) pour
définir un bloc de transaction.
LOCK TABLE
ne concernent que les verrous de niveau table.
Les noms de mode contenant ROW
sont donc tous mal nommés. Ces
noms de modes doivent généralement être compris comme indiquant l'intention de
l'utilisateur d'acquérir des verrous de niveau ligne à l'intérieur de la
table verrouillée. Le mode ROW EXCLUSIVE
est également un verrou
de table partageable. Tous les modes de verrou ont des
sémantiques identiques en ce qui concerne LOCK TABLE
;
ils ne diffèrent que dans les règles de conflit entre les modes. Pour des
informations sur la façon d'acquérir un vrai verrou de niveau ligne, voir
Section 13.3.2 et
Clause de verrouillage
dans la documentation de référence de SELECT.
Obtenir un verrou SHARE
sur une table avec clé primaire avant
de réaliser des insertions dans une table disposant de la clé
étrangère :
BEGIN WORK; LOCK TABLE films IN SHARE MODE; SELECT id FROM films WHERE nom = 'Star Wars : Episode I - La menace fantôme'; -- Effectuer un ROLLBACK si aucun enregistrement n'est retourné INSERT INTO commentaires_films VALUES (_id_, 'SUPER ! Je l''attendais depuis si longtemps !'); COMMIT WORK;
Prendre un verrou SHARE ROW EXCLUSIVE
sur une table avec clé
primaire lors du début des opérations de suppression :
BEGIN WORK; LOCK TABLE films IN SHARE ROW EXCLUSIVE MODE; DELETE FROM commentaires_films WHERE id IN (SELECT id FROM films WHERE score < 5); DELETE FROM films WHERE score < 5; COMMIT WORK;
LOCK TABLE
n'existe pas dans le standard SQL. À la
place, il utilise SET TRANSACTION
pour spécifier les niveaux
de concurrence entre transactions. PostgreSQL en
dispose également ; voir
SET TRANSACTION pour les détails.
À l'exception des modes de verrous ACCESS SHARE
,
ACCESS EXCLUSIVE
et SHARE UPDATE EXCLUSIVE
,
les modes de verrou PostgreSQL et la syntaxe
LOCK TABLE
sont compatibles avec ceux présents dans
Oracle.