Documentation PostgreSQL 15.15 » Référence » Commandes SQL » LOCK

Précédent | Niveau supérieur | Suivant
LOAD | Sommaire | MERGE

## LOCK

LOCK — verrouiller une table

## Synopsis

    LOCK [ TABLE ] [ ONLY ] nom [ * ] [, ...] [ IN mode_verrou MODE ] [ NOWAIT ]

    où mode_verrou peut être :

        ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE

## Description

`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 `nom` IN SHARE MODE` attend que tout détenteur concurrent de verrous de mode `ROW 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.

## Paramètres

`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.

## Notes

`LOCK TABLE ... IN ACCESS SHARE MODE` requiert les droits `SELECT` sur la table cible. `LOCK TABLE ... IN ROW EXCLUSIVE MODE` requiert des droits `INSERT`, `UPDATE`, `DELETE`, ou `TRUNCATE` sur la table cible. Toutes les autres formes de `LOCK` requièrent au moins un des droits `UPDATE`, `DELETE` et `TRUNCATE` au niveau table.

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.

## Exemples

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;

## Compatibilité

`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.