Nell'esempio di codice che hai fornito, tutte le letture di quella riga vedranno il vecchio valore fino a quando la transazione non viene confermata.
1) Considerare che l'esempio di codice venga eseguito due volte contemporaneamente, con lo stesso valore di X
. Se l'istanza A è stata eseguita select ... for update
, ha bloccato quella riga fino al commit. L'istanza B, facendo lo stesso, si bloccherà nel tentativo di prendere la serratura allo stesso modo. Solo quando A si impegna, B può continuare. B otterrà quindi il valore A lasciato indietro nel suo aggiornamento finale.
Se Y
dipende dal valore select ... for update
letto dalla query o da un'altra lettura nella parte "complessa", ciò avrà lo stesso effetto che se fossero eseguiti in serie: non si ottiene la condizione della competizione in cui si troverà uno dei risultati scartato.
Se Y
è puramente il risultato delle complesse query nel mezzo, quindi eseguirlo in parallelo senza select ... for update
che entrambi eseguiranno lo stesso aggiornamento.
2) for share
consentirà ad altre selezioni su quella riga di procedere, ma provocherà qualsiasi altro tentativo di bloccare select ... for update
o update ...
bloccare fino al completamento. Se il codice di esempio viene eseguito due volte, contemporaneamente, si bloccherebbero al raggiungimento update
dell'istruzione, causando l'interruzione di uno di essi.
3) No. Fare questo è pericoloso, dal momento che un lettore potrebbe leggere un campo mezzo aggiornato. (Oppure leggi il resto di un campo aggiornato dopo l'inizio della lettura.) Può anche interrompere la coerenza, mostrando al lettore un valore aggiornato dopo l'inizio della sua transazione.