Il blocco delle tabelle impedisce ad altri utenti di DB di influenzare le righe / tabelle che hai bloccato. Ma i blocchi, di per sé, NON assicureranno che la tua logica esca in uno stato coerente.
Pensa a un sistema bancario. Quando paghi una fattura online, ci sono almeno due account interessati dalla transazione: il tuo account, da cui viene prelevato il denaro. E il conto del destinatario, in cui viene trasferito il denaro. E il conto della banca, sul quale depositeranno felicemente tutte le commissioni di servizio addebitate sulla transazione. Dato (come tutti sanno oggigiorno) che le banche sono straordinariamente stupide, diciamo che il loro sistema funziona in questo modo:
$balance = "GET BALANCE FROM your ACCOUNT";
if ($balance < $amount_being_paid) {
charge_huge_overdraft_fees();
}
$balance = $balance - $amount_being paid;
UPDATE your ACCOUNT SET BALANCE = $balance;
$balance = "GET BALANCE FROM receiver ACCOUNT"
charge_insane_transaction_fee();
$balance = $balance + $amount_being_paid
UPDATE receiver ACCOUNT SET BALANCE = $balance
Ora, senza blocchi e transazioni, questo sistema è vulnerabile a varie condizioni di gara, la più grande delle quali è l'esecuzione di più pagamenti sul tuo account o sull'account del destinatario in parallelo. Mentre il tuo codice ha recuperato il tuo saldo e sta facendo il huge_overdraft_fees () e quant'altro, è del tutto possibile che qualche altro pagamento esegua lo stesso tipo di codice in parallelo. Recupereranno il tuo saldo (diciamo $ 100), faranno le loro transazioni (prendi i $ 20 che stai pagando e i $ 30 con cui ti stanno fregando), e ora entrambi i percorsi del codice hanno due saldi diversi: $ 80 e $ 70. A seconda di quale finisce per ultimo, ti ritroverai con uno di quei due saldi nel tuo account, invece dei $ 50 con cui avresti dovuto finire ($ 100 - $ 20 - $ 30). In questo caso, "errore bancario a tuo favore"
Ora, diciamo che usi i lucchetti. Il pagamento della bolletta ($ 20) colpisce per primo il tubo, quindi vince e blocca il record del tuo account. Ora hai un uso esclusivo e puoi detrarre i $ 20 dal saldo e riscrivere il nuovo saldo in pace ... e il tuo account finisce con $ 80 come previsto. Ma ... uhoh ... provi ad aggiornare l'account del destinatario, ed è bloccato, e bloccato più a lungo di quanto il codice permetta, facendo scadere la tua transazione ... Abbiamo a che fare con banche stupide, quindi invece di avere un errore corretto maneggiando, il codice tira semplicemente un exit()
e i tuoi $ 20 svaniscono in uno sbuffo di elettroni. Ora sei fuori $ 20, e devi ancora $ 20 al ricevitore, e il tuo telefono viene recuperato.
Quindi ... inserisci le transazioni. Inizi una transazione, addebiti $ 20 sul tuo conto, provi ad accreditare $ 20 al destinatario ... e qualcosa esplode di nuovo. Ma questa volta, invece di exit()
, il codice può semplicemente fare rollback
, e puff, i tuoi $ 20 vengono aggiunti magicamente al tuo account.
Alla fine, si riduce a questo:
I blocchi impediscono a chiunque altro di interferire con i record del database con cui hai a che fare. Le transazioni impediscono a qualsiasi errore "successivo" di interferire con le cose "precedenti" che hai fatto. Nessuno dei due da solo può garantire che le cose vadano bene alla fine. Ma insieme lo fanno.
nella lezione di domani: The Joy of Deadlocks.