Usar SELECT FOR UPDATE en el aislamiento de lectura repetible

En esta página se describe cómo usar la cláusula FOR UPDATE en el aislamiento de lectura repetible.

El mecanismo de bloqueo de la cláusula FOR UPDATE es diferente para el aislamiento de lectura repetible y serializable. A diferencia del aislamiento serializable, la cláusula FOR UPDATE no adquiere bloqueos en el aislamiento de lectura repetible. Para obtener más información sobre los bloqueos en FOR UPDATE, consulta Usar SELECT FOR UPDATE en el aislamiento serializable.

Para saber cómo usar la cláusula FOR UPDATE, consulta las guías de referencia de GoogleSQL y PostgreSQL FOR UPDATE.

Por qué usar la cláusula FOR UPDATE

Cuando se ejecuta una transacción con aislamiento de lectura repetible, los datos consultados por la instrucción SELECT siempre se devuelven en la marca de tiempo de la instantánea establecida para la transacción. Si la transacción hace actualizaciones basadas en los datos consultados, puede haber problemas de corrección si una transacción simultánea también actualiza los datos consultados. Para obtener más información, consulta Conflictos de lectura y escritura y corrección.

Para asegurarse de que los datos consultados por la instrucción SELECT sigan siendo válidos cuando se confirme la transacción, puede usar una cláusula FOR UPDATE con aislamiento de lectura repetible. El uso de FOR UPDATE garantiza la corrección de las transacciones a pesar de los conflictos de lectura y escritura en los que otra transacción podría haber modificado los datos entre el momento en que se leyeron y el momento en que se modificaron.

Sintaxis de consulta

En esta sección se ofrecen directrices sobre la sintaxis de las consultas al usar la cláusula FOR UPDATE.

El uso más habitual es en una instrucción SELECT de nivel superior. Por ejemplo:

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

La cláusula FOR UPDATE asegura que los datos consultados por la instrucción SELECT y SingerID = 5 sigan siendo válidos cuando se confirme la transacción, lo que evita problemas de corrección que podrían surgir si una transacción simultánea actualiza los datos consultados.

Usar en instrucciones WITH

La cláusula FOR UPDATE no verifica los intervalos analizados en la instrucción WITH cuando se especifica FOR UPDATE en la consulta de nivel externo de la instrucción WITH.

En la siguiente consulta, no se valida ningún intervalo analizado porque FOR UPDATE no se propaga a la consulta de expresiones de tabla comunes (CTE).

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

Si se especifica la cláusula FOR UPDATE en la consulta CTE, se valida el intervalo analizado de la consulta CTE.

En el siguiente ejemplo, se validan las celdas SingerId y SingerInfo de las filas donde SingerId > 5.

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

Usar en subconsultas

Puedes usar la cláusula FOR UPDATE en una consulta de nivel externo que tenga una o más subconsultas. Los intervalos analizados por la consulta de nivel superior y en las subconsultas se validan, excepto en las subconsultas de expresiones.

La siguiente consulta valida las celdas SingerId y SingerInfo de las filas en las que SingerId > 5.

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

La siguiente consulta no valida ninguna celda de la tabla Albums porque está dentro de una subconsulta de expresión. Se validan las celdas SingerId y SingerInfo de las filas devueltas por la subconsulta de la expresión.

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

Se usa para consultar vistas.

Puedes usar la cláusula FOR UPDATE para consultar una vista, como se muestra en el siguiente ejemplo:

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

SELECT * FROM SingerBio WHERE SingerId = 5 FOR UPDATE;

No puedes usar la cláusula FOR UPDATE cuando definas una vista.

Casos prácticos no admitidos

No se admiten los siguientes casos prácticos de FOR UPDATE:

  • Como mecanismo de exclusión mutua para ejecutar código fuera de Spanner: no uses el bloqueo en Spanner para asegurar el acceso exclusivo a un recurso fuera de Spanner. Por ejemplo, Spanner puede anular transacciones si se vuelve a intentar una transacción, ya sea de forma explícita mediante código de aplicación o de forma implícita mediante código de cliente, como el controlador JDBC de Spanner. En este caso, solo se garantiza que los bloqueos se mantengan durante el intento que se haya confirmado.
  • En combinación con la sugerencia LOCK_SCANNED_RANGES: No puedes usar la cláusula FOR UPDATE y la sugerencia LOCK_SCANNED_RANGES en la misma consulta. De lo contrario, Spanner devolverá un error. Para obtener más información, consulta la comparación con la sugerencia LOCK_SCANNED_RANGES.
  • En las consultas de búsqueda en todo el texto: no puedes usar la cláusula FOR UPDATE en las consultas que usen índices de búsqueda en todo el texto.
  • En las transacciones de solo lectura: la cláusula FOR UPDATE solo es válida en las consultas que se ejecutan en transacciones de lectura y escritura.
  • En las instrucciones DDL: no puedes usar la cláusula FOR UPDATE en las consultas de las instrucciones DDL, que se almacenan para ejecutarse más adelante. Por ejemplo, no puedes usar la cláusula FOR UPDATE al definir una vista.

Siguientes pasos