Usar SELECT FOR UPDATE no isolamento de leitura repetível

Nesta página, descrevemos como usar a cláusula FOR UPDATE no isolamento de leitura repetida.

O mecanismo de bloqueio da cláusula FOR UPDATE é diferente para leitura repetível e isolamento serializável. Ao contrário do isolamento serializável, a cláusula FOR UPDATE não adquire bloqueios no isolamento de leitura repetível. Para mais informações sobre bloqueios em FOR UPDATE, consulte Usar SELECT FOR UPDATE em isolamento serializável.

Para saber como usar a cláusula FOR UPDATE, consulte os guias de referência do GoogleSQL e do PostgreSQL FOR UPDATE.

Por que usar a cláusula FOR UPDATE

Quando uma transação é executada com isolamento de leitura repetível, os dados consultados pela instrução SELECT sempre são retornados no carimbo de data/hora do snapshot estabelecido para a transação. Se a transação fizer atualizações com base nos dados consultados, poderá haver problemas de correção se uma transação simultânea também atualizar os dados consultados. Para mais informações, consulte Conflitos de leitura e gravação e correção.

Para garantir que os dados consultados pela instrução SELECT ainda sejam válidos quando a transação for confirmada, use uma cláusula FOR UPDATE com isolamento de leitura repetível. O uso de FOR UPDATE garante a correção da transação apesar de conflitos de leitura/gravação em que os dados podem ter sido modificados por outra transação entre o momento em que foram lidos e modificados.

Sintaxe das consultas

Esta seção fornece orientações sobre a sintaxe de consulta ao usar a cláusula FOR UPDATE.

O uso mais comum é em uma instrução SELECT de nível superior. Exemplo:

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

A cláusula FOR UPDATE garante que os dados consultados pela instrução SELECT e SingerID = 5 ainda sejam válidos quando a transação for confirmada, evitando problemas de correção que podem surgir se uma transação simultânea atualizar os dados consultados.

Uso em instruções WITH

A cláusula FOR UPDATE não verifica os intervalos verificados na instrução WITH quando você especifica FOR UPDATE na consulta de nível externo da instrução WITH.

Na consulta a seguir, nenhum intervalo verificado é validado porque o FOR UPDATE não é propagado para a consulta de expressões de tabela comuns (CTE).

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

Se a cláusula FOR UPDATE for especificada na consulta de CTE, o intervalo verificado da consulta de CTE será validado.

No exemplo a seguir, as células SingerId e SingerInfo das linhas em que SingerId > 5 são validadas.

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

Uso em subconsultas

É possível usar a cláusula FOR UPDATE em uma consulta de nível externo que tenha uma ou mais subconsultas. Os intervalos verificados pela consulta de nível superior e nas subconsultas são validados, exceto em subconsultas de expressão.

A consulta a seguir valida as células SingerId e SingerInfo para linhas em que SingerId > 5.

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

A consulta a seguir não valida nenhuma célula na tabela Albums porque está em uma subconsulta de expressão. As células SingerId e SingerInfo das linhas retornadas pela subconsulta de expressão são validadas.

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

Usado para consultar visualizações

Você pode usar a cláusula FOR UPDATE para consultar uma visualização, conforme mostrado no exemplo a seguir:

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

SELECT * FROM SingerBio WHERE SingerId = 5 FOR UPDATE;

Não é possível usar a cláusula FOR UPDATE ao definir uma visualização.

Casos de uso não aceitos

Os seguintes casos de uso do FOR UPDATE não são compatíveis:

  • Como um mecanismo de exclusão mútua para execução de código fora do Spanner:não use o bloqueio no Spanner para garantir acesso exclusivo a um recurso fora dele. As transações podem ser canceladas pelo Spanner, por exemplo, se uma transação for repetida, seja explicitamente pelo código do aplicativo ou implicitamente pelo código do cliente, como o driver JDBC do Spanner, só é garantido que os bloqueios sejam mantidos durante a tentativa que foi executada.
  • Em combinação com a dica LOCK_SCANNED_RANGES:não é possível usar a cláusula FOR UPDATE e a dica LOCK_SCANNED_RANGES na mesma consulta. Caso contrário, o Spanner vai retornar um erro. Para mais informações, consulte Comparação com a dica LOCK_SCANNED_RANGES.
  • Em consultas de pesquisa de texto completo:não é possível usar a cláusula FOR UPDATE em consultas que usam índices de pesquisa de texto completo.
  • Em transações somente leitura:a cláusula FOR UPDATE só é válida em consultas executadas em transações de leitura e gravação.
  • Em instruções DDL:não é possível usar a cláusula FOR UPDATE em consultas dentro de instruções DDL, que são armazenadas para execução posterior. Por exemplo, não é possível usar a cláusula FOR UPDATE ao definir uma visualização.

A seguir