Il blocco delle tabelle impedisce ad altri utenti DB di influenzare le righe/tabelle che hai bloccato. Ma i blocchi, in sé e per sé, NON garantiranno che la tua logica esca in uno stato coerente.
Pensa a un sistema bancario. Quando paghi una fattura online, ci sono almeno due conti interessati dalla transazione:Il tuo conto, da cui viene prelevato il denaro. E il conto del destinatario, su cui viene trasferito il denaro. E il conto della banca, sul quale depositeranno volentieri tutte le commissioni di servizio addebitate sulla transazione. Dato (come tutti sanno in questi giorni) che le banche sono straordinariamente stupide, diciamo che il loro sistema funziona così:
$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 senza transazioni, questo sistema è vulnerabile a varie condizioni di gara, la più grande delle quali è l'esecuzione di più pagamenti sul tuo account o l'account del destinatario in parallelo. Mentre il tuo codice ha recuperato il tuo saldo e sta facendo huge_overdraft_fees() e quant'altro, è del tutto possibile che qualche altro pagamento eseguirà lo stesso tipo di codice in parallelo. Recupereranno il tuo saldo (diciamo, $ 100), eseguiranno le loro transazioni (tira fuori 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 chi finisce per ultimo, ti ritroverai con uno di questi 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) arriva per primo, quindi vince e blocca il record del tuo account. Ora hai un uso esclusivo e puoi detrarre $ 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 consentito dal codice, timeout della transazione... Abbiamo a che fare con banche stupide, quindi invece di avere un errore corretto gestione, il codice estrae 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 ricevitore... e qualcosa esplode di nuovo. Ma questa volta, invece di exit()
, il codice può semplicemente eseguire il rollback
e puff, i tuoi $ 20 vengono magicamente aggiunti 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 evitano che eventuali errori "successivi" interferiscano con le cose "precedenti" che hai fatto. Nessuno dei due da solo può garantire che le cose alla fine vadano bene. Ma insieme, lo fanno.
nella lezione di domani:The Joy of Deadlocks.