Utiliser SELECT FOR UPDATE dans l'isolation de lecture répétable

Cette page explique comment utiliser la clause FOR UPDATE dans l'isolation de lecture répétable.

Le mécanisme de verrouillage de la clause FOR UPDATE est différent pour l'isolation de lecture reproductible et sérialisable. Contrairement à l'isolation sérialisable, la clause FOR UPDATE n'acquiert pas de verrous dans l'isolation de lecture répétable. Pour en savoir plus sur les verrous dans FOR UPDATE, consultez Utiliser SELECT FOR UPDATE dans l'isolation sérialisable.

Pour savoir comment utiliser la clause FOR UPDATE, consultez les guides de référence GoogleSQL et PostgreSQL pour FOR UPDATE.

Pourquoi utiliser la clause FOR UPDATE ?

Lorsqu'une transaction s'exécute avec un niveau d'isolation "repeatable read", les données interrogées par l'instruction SELECT sont toujours renvoyées à l'horodatage de l'instantané établi pour la transaction. Si la transaction effectue ensuite des mises à jour en fonction des données interrogées, des problèmes d'exactitude peuvent survenir si une transaction simultanée met également à jour les données interrogées. Pour en savoir plus, consultez Conflits de lecture/écriture et exactitude.

Pour vous assurer que les données interrogées par l'instruction SELECT sont toujours valides lorsque la transaction est validée, vous pouvez utiliser une clause FOR UPDATE avec un niveau d'isolation de lecture "repeatable read". L'utilisation de FOR UPDATE garantit la correction des transactions malgré les conflits de lecture/écriture, où les données peuvent avoir été modifiées par une autre transaction entre le moment où elles ont été lues et celui où elles ont été modifiées.

Syntaxe des requêtes

Cette section fournit des conseils sur la syntaxe des requêtes lorsque vous utilisez la clause FOR UPDATE.

L'utilisation la plus courante se fait dans une instruction SELECT de premier niveau. Exemple :

SELECT SingerId, SingerInfo
FROM Singers WHERE SingerID = 5
FOR UPDATE;

La clause FOR UPDATE garantit que les données interrogées par l'instruction SELECT et SingerID = 5 sont toujours valides lorsque la transaction est validée. Cela permet d'éviter les problèmes d'exactitude qui pourraient survenir si une transaction simultanée met à jour les données interrogées.

Utilisation dans les instructions WITH

La clause FOR UPDATE ne vérifie pas les plages analysées dans l'instruction WITH lorsque vous spécifiez FOR UPDATE dans la requête de niveau extérieur de l'instruction WITH.

Dans la requête suivante, aucune plage analysée n'est validée, car FOR UPDATE n'est pas propagé à la requête d'expression de table commune (CTE).

WITH s AS (SELECT SingerId, SingerInfo FROM Singers WHERE SingerID > 5)
SELECT * FROM s
FOR UPDATE;

Si la clause FOR UPDATE est spécifiée dans la requête CTE, la plage analysée de la requête CTE est validée.

Dans l'exemple suivant, les cellules SingerId et SingerInfo des lignes où SingerId > 5 sont validées.

WITH s AS
  (SELECT SingerId, SingerInfo FROM Singers WHERE SingerId > 5 FOR UPDATE)
SELECT * FROM s;

Utilisation dans les sous-requêtes

Vous pouvez utiliser la clause FOR UPDATE dans une requête de niveau externe comportant une ou plusieurs sous-requêtes. Les plages analysées par la requête de niveau supérieur et dans les sous-requêtes sont validées, sauf dans les sous-requêtes d'expression.

La requête suivante valide les cellules SingerId et SingerInfo pour les lignes où SingerId > 5..

(SELECT SingerId, SingerInfo FROM Singers WHERE SingerId > 5) AS t
FOR UPDATE;

La requête suivante ne valide aucune cellule de la table Albums, car elle se trouve dans une sous-requête d'expression. Les cellules SingerId et SingerInfo des lignes renvoyées par la sous-requête d'expression sont validées.

SELECT SingerId, SingerInfo
FROM Singers
WHERE SingerId = (SELECT SingerId FROM Albums WHERE MarketingBudget > 100000)
FOR UPDATE;

Utiliser pour interroger les vues

Vous pouvez utiliser la clause FOR UPDATE pour interroger une vue, comme illustré dans l'exemple suivant :

CREATE VIEW SingerBio AS SELECT SingerId, FullName, SingerInfo FROM Singers;

SELECT * FROM SingerBio WHERE SingerId = 5 FOR UPDATE;

Vous ne pouvez pas utiliser la clause FOR UPDATE lors de la définition d'une vue.

Cas d'utilisation non compatibles

Les cas d'utilisation suivants de FOR UPDATE ne sont pas pris en charge :

  • En tant que mécanisme d'exclusion mutuelle pour l'exécution de code en dehors de Spanner : n'utilisez pas le verrouillage dans Spanner pour garantir un accès exclusif à une ressource en dehors de Spanner. Les transactions peuvent être annulées par Spanner, par exemple si une transaction est relancée, que ce soit explicitement par un code d'application ou implicitement par un code client, tel que le pilote JDBC Spanner. La seule garantie est le maintien des verrous pendant la tentative réellement effectuée.
  • En combinaison avec l'indication LOCK_SCANNED_RANGES : vous ne pouvez pas utiliser à la fois la clause FOR UPDATE et l'indication LOCK_SCANNED_RANGES dans la même requête. Dans le cas contraire, Spanner renvoie une erreur. Pour en savoir plus, consultez Comparaison avec l'indice LOCK_SCANNED_RANGES.
  • Dans les requêtes de recherche en texte intégral : vous ne pouvez pas utiliser la clause FOR UPDATE dans les requêtes utilisant des index de recherche en texte intégral.
  • Dans les transactions en lecture seule : la clause FOR UPDATE n'est valide que dans les requêtes exécutées dans des transactions en lecture-écriture.
  • Dans les instructions LDD : vous ne pouvez pas utiliser la clause FOR UPDATE dans les requêtes des instructions LDD, qui sont stockées pour être exécutées ultérieurement. Par exemple, vous ne pouvez pas utiliser la clause FOR UPDATE lors de la définition d'une vue.

Étape suivante