Sì e No - come al solito, dipende. La documentazione dice rigorosamente che:
In altre parole, semplicemente SELECT è diverso da SELECT FOR UPDATE/DELETE/UPDATE.
Puoi creare un semplice test case per osservare quel comportamento:
Sessione 1
test=> START TRANSACTION;
START TRANSACTION
test=> SELECT * FROM test;
x
----
1
2
3
4
5
6
7
8
9
10
(10 rows)
test=> DELETE FROM test;
DELETE 10
test=>
Ora accedi in un'altra Sessione 2:
test=> START TRANSACTION;
START TRANSACTION
test=> SELECT * FROM test;
x
----
1
2
3
4
5
6
7
8
9
10
(10 rows)
test=> SELECT * FROM test WHERE x = 5 FOR UPDATE;
Dopo l'ultimo comando SELECT ... FOR UPDATE
la sessione 1 "si blocca" ed è in attesa di qualcosa ......
Di nuovo nella sessione 1
test=> insert into test select * from generate_series(1,10);
INSERT 0 10
test=> commit;
COMMIT
E ora, quando torni alla sessione 2, vedrai questo:
test=> SELECT * FROM test WHERE x = 5 FOR UPDATE;
x
---
(0 rows)
test=> select * from test;
x
----
1
2
3
4
5
6
7
8
9
10
(10 rows)
Cioè - semplice SELECT
continua a non vedere alcuna modifica, mentre SELECT ... FOR UPDATE
vede che le righe sono state eliminate. Ma non vede nuove righe inserite dalla sessione 1
In effetti una sequenza che stai vedendo è:
- Il processo A avvia la sua transazione
- Il processo A elimina tutto dalla tabella T
- il processo B avvia la sua transazione
- Il processo B tenta una selezione per l'aggiornamento su una riga nella tabella T
- Il processo B "si blocca" e attende fino a quando la sessione A non esegue un commit o un rollback
- Il processo A ripopola la tabella T dai dati in entrata
- Il processo A esegue il commit della sua transazione
- Il processo B risulta vuoto (0 righe dopo il commit della sessione A) e chiama il rollback