Utilizzare SELECT FOR UPDATE nell'isolamento di lettura ripetibile

Questa pagina descrive come utilizzare la clausola FOR UPDATE nell'isolamento di lettura ripetibile.

Il meccanismo di blocco della clausola FOR UPDATE è diverso per l'isolamento serializzabile e di lettura ripetibile. A differenza dell'isolamento serializzabile, la clausola FOR UPDATE non acquisisce blocchi nell'isolamento di lettura ripetibile. Per ulteriori informazioni sui blocchi in FOR UPDATE, consulta Utilizzare SELECT FOR UPDATE nell'isolamento serializzabile.

Per scoprire come utilizzare la clausola FOR UPDATE, consulta le guide di riferimento di GoogleSQL e PostgreSQL FOR UPDATE.

Perché utilizzare la clausola FOR UPDATE

Quando una transazione viene eseguita con l'isolamento di lettura ripetibile, i dati interrogati dall'istruzione SELECT vengono sempre restituiti al timestamp dello snapshot stabilito per la transazione. Se la transazione esegue aggiornamenti in base ai dati sottoposti a query, potrebbero verificarsi problemi di correttezza se anche una transazione simultanea aggiorna i dati sottoposti a query. Per ulteriori informazioni, vedi Conflitti di lettura/scrittura e correttezza.

Per garantire che i dati interrogati dall'istruzione SELECT siano ancora validi quando viene eseguito il commit della transazione, puoi utilizzare una clausola FOR UPDATE con isolamento di lettura ripetibile. L'utilizzo di FOR UPDATE garantisce la correttezza della transazione nonostante i conflitti di lettura/scrittura in cui i dati potrebbero essere stati modificati da un'altra transazione tra il momento della lettura e quello della modifica.

Sintassi delle query

Questa sezione fornisce indicazioni sulla sintassi delle query quando utilizzi la clausola FOR UPDATE.

L'utilizzo più comune è in un'istruzione SELECT di primo livello. Ad esempio:

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

La clausola FOR UPDATE garantisce che i dati interrogati dall'istruzione SELECT e da SingerID = 5 siano ancora validi quando viene eseguito il commit della transazione, evitando problemi di correttezza che potrebbero verificarsi se una transazione simultanea aggiorna i dati interrogati.

Utilizzo nelle istruzioni WITH

La clausola FOR UPDATE non verifica gli intervalli analizzati all'interno dell'istruzione WITH quando specifichi FOR UPDATE nella query di livello esterno dell'istruzione WITH.

Nella seguente query, nessun intervallo scansionato viene convalidato perché FOR UPDATE non viene propagato alla query dell'espressione della tabella comune (CTE).

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

Se la clausola FOR UPDATE è specificata nella query CTE, viene convalidato l'intervallo scansionato della query CTE.

Nell'esempio seguente, le celle SingerId e SingerInfo per le righe in cui SingerId > 5 vengono convalidate.

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

Utilizzo nelle sottoquery

Puoi utilizzare la clausola FOR UPDATE in una query di livello esterno che contiene una o più subquery. Gli intervalli analizzati dalla query di primo livello e all'interno delle subquery vengono convalidati, tranne nelle subquery di espressione.

La seguente query convalida le celle SingerId e SingerInfo per le righe in cui SingerId > 5.

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

La seguente query non convalida alcuna cella nella tabella Albums perché si trova all'interno di una sottoquery di espressione. Le celle SingerId e SingerInfo per le righe restituite dalla sottoquery dell'espressione vengono convalidate.

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

Utilizzare per eseguire query sulle visualizzazioni

Puoi utilizzare la clausola FOR UPDATE per eseguire una query su una vista come mostrato nell'esempio seguente:

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

SELECT * FROM SingerBio WHERE SingerId = 5 FOR UPDATE;

Non puoi utilizzare la clausola FOR UPDATE quando definisci una vista.

Casi d'uso non supportati

I seguenti casi d'uso di FOR UPDATE non sono supportati:

  • Come meccanismo di esclusione reciproca per l'esecuzione di codice al di fuori di Spanner: non utilizzare il blocco in Spanner per garantire l'accesso esclusivo a una risorsa al di fuori di Spanner. Le transazioni potrebbero essere interrotte da Spanner, ad esempio, se una transazione viene ritentata, in modo esplicito dal codice dell'applicazione o implicito dal codice client, ad esempio il driver JDBC di Spanner, è garantito che i blocchi vengano mantenuti durante il tentativo di commit.
  • In combinazione con il suggerimento LOCK_SCANNED_RANGES: Non puoi utilizzare sia la clausola FOR UPDATE sia il suggerimento LOCK_SCANNED_RANGES nella stessa query, altrimenti Spanner restituisce un errore. Per ulteriori informazioni, consulta Confronto con il suggerimento LOCK_SCANNED_RANGES.
  • Nelle query di ricerca full-text:non puoi utilizzare la clausola FOR UPDATE nelle query che utilizzano indici di ricerca full-text.
  • Nelle transazioni di sola lettura:la clausola FOR UPDATE è valida solo nelle query eseguite all'interno delle transazioni di lettura/scrittura.
  • All'interno delle istruzioni DDL:non puoi utilizzare la clausola FOR UPDATE nelle query all'interno delle istruzioni DDL, che vengono archiviate per l'esecuzione successiva. Ad esempio, non puoi utilizzare la clausola FOR UPDATE quando definisci una vista.

Passaggi successivi