race condition UPDATE modifica della colonna di credito - cosa succede sul rollback?
-
26-09-2019 - |
Domanda
ok, ho provato a cercare e non ho trovato una risposta a questo - Sono curioso come il rollback condizioni maniglie di gara. Ad esempio:
Se ho una tabella (CompanyAccount), che tiene traccia di quanti crediti di una società ha a disposizione per l'acquisto (c'è solo una riga in una tabella del database per azienda) e ci sono potenzialmente più utenti della stessa azienda che può diminuire i crediti dal conto singola azienda, cosa succede in caso di errore quando si verifica un ROLLBACK?
Esempio:
Ipotesi: ho scritto l'aggiornamento corretto per calcolare il "Credito" nuovo equilibrio, invece di indovinare ciò che il nuovo equilibrio di credito è (cioè non proviamo a dire l'istruzione UPDATE ciò che il nuovo equilibrio di credito / valore, abbiamo dire prendere tutto ciò che è nella colonna di credito e sottrarre il mio valore di decremento nell'istruzione UPDATE) ...
qui è un esempio di come l'istruzione di aggiornamento è scritto:
UPDATE dbo.CompanyAccount SET Credit = credito - @DecrementAmount DOVE CompanyAccountId = @CompanyAccountId
Se la colonna "Credito" ha 10.000 crediti. L'utente A provoca un decremento di 4.000 crediti e l'utente B provoca un decremento di 1000 crediti. Per qualche ragione un rollback viene attivato durante il decremento per l'utente A (ci sono circa 1/2 dozzina di tavoli con le righe per inserirsi durante la transazione). Se l'utente A vince la condizione di competizione e il nuovo equilibrio è di 6.000 (ma non ancora COMMIT'ed) cosa succede in caso di decremento per l'utente B prima di applicare il rollback? non la colonna bilancia vanno da 6.000 a 5.000 e poi si fa ROLLBACK a 10.000?
Non sto troppo chiaro su come il ROLLBACK gestirà questo. Forse sto di semplificare eccessivamente. Qualcuno può dirmi se mi fraintendere come ROLLBACK funzionerà o se ci sono altri rischi ho bisogno di preoccuparsi per questo stile.
Grazie per il vostro input.
Soluzione
Nell'esempio si hanno dato non ci sarà alcun problema.
La prima operazione avrà un blocco esclusivo che significa la seconda non può modificare quella riga fino a dopo il primo ha commesso o rollback. Sarà solo aspettare (bloccato) fino a quando il blocco viene rilasciato.
Si diventa un po 'più complicato se si dispone di più istruzioni. Probabilmente si dovrebbe leggere su diversi livelli di isolamento e come possono consentire o impedire fenomeni come "aggiornamenti perduti".
Altri suggerimenti
Ripristino fa parte della transazione e si blocca sarà mantenuta durante il rollback. Il * A * Tomic in acido. L'utente B non comincerà fino a quando tutti i blocchi vengono rilasciati.
Quello che succede:
- serrature utente Una fila
- L'utente B non vedrà le righe fino serrature vengono rilasciati
- utente passa una schiena, serrature di rilascio, cambia mai successo.
- L'utente B vede le righe. -1000 si tradurrà in 9000
Tuttavia, se l'utente B ha già letto l'equilibrio allora il mio essere incoerente quando si tratta di UPDATE. Dipende da quello che si sta effettivamente facendo e in quale ordine, da qui la necessità di capire livelli di isolamento (ed i problemi con phantom e non ripetibile legge)
Un'alternativa al SERIALIZABLE o REPEATABLE LEGGI può utilizzare sp_getapplock in modalità di transazione per le parti di semaforo della transazione.