Het vergrendelen van tabellen voorkomt dat andere DB-gebruikers de rijen/tabellen die u hebt vergrendeld, beïnvloeden. Maar sloten op zichzelf zullen er NIET voor zorgen dat uw logica in een consistente staat naar buiten komt.
Denk aan een banksysteem. Wanneer u online een rekening betaalt, zijn er ten minste twee rekeningen die door de transactie worden beïnvloed:uw rekening, waarvan het geld wordt afgeschreven. En de rekening van de ontvanger, waarop het geld wordt overgemaakt. En de rekening van de bank, waarop ze graag alle servicekosten storten die op de transactie in rekening worden gebracht. Aangezien (zoals iedereen tegenwoordig weet) dat banken buitengewoon dom zijn, laten we zeggen dat hun systeem als volgt werkt:
$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
Nu, zonder vergrendelingen en zonder transacties, is dit systeem kwetsbaar voor verschillende race-omstandigheden, waarvan de grootste is dat meerdere betalingen worden uitgevoerd op uw account of op de rekening van de ontvanger tegelijk. Terwijl uw code uw saldo heeft opgehaald en de huge_overdraft_fees() en wat al niet meer doet, is het heel goed mogelijk dat een andere betaling hetzelfde type code parallel uitvoert. Ze halen je saldo op (zeg $ 100), doen hun transacties (haal de $ 20 die je betaalt en de $ 30 waarmee ze je belazeren), en nu hebben beide codepaden twee verschillende saldi:$ 80 en $ 70. Afhankelijk van welke als laatste eindigen, krijg je een van die twee saldi in je account, in plaats van de $ 50 die je had moeten krijgen ($ 100 - $ 20 - $ 30). In dit geval "bankfout in uw voordeel".
Laten we zeggen dat u sloten gebruikt. Uw factuurbetaling ($ 20) raakt als eerste de pijp, dus deze wint en vergrendelt uw accountrecord. Nu heb je exclusief gebruik en kun je de $ 20 van het saldo aftrekken, en het nieuwe saldo in alle rust terugschrijven ... en je account eindigt met $ 80 zoals verwacht. Maar... uhoh... Je probeert de rekening van de ontvanger bij te werken, en het is vergrendeld, en langer vergrendeld dan de code toestaat, waardoor je transactie wordt getimed... We hebben te maken met domme banken, dus in plaats van een fout te maken afhandeling, trekt de code gewoon een exit()
, en je $ 20 verdwijnt in een wolk van elektronen. Nu ben je $ 20 kwijt, en je bent nog $ 20 schuldig aan de ontvanger, en je telefoon wordt teruggenomen.
Dus... transacties invoeren. Je start een transactie, je debiteert $20 van je rekening, je probeert de ontvanger $20 te crediteren... en er ontploft weer iets. Maar deze keer, in plaats van exit()
, de code kan gewoon rollback
, en poef, je $ 20 is op magische wijze weer toegevoegd aan je account.
Uiteindelijk komt het hierop neer:
Sloten zorgen ervoor dat niemand anders zich bemoeit met databaserecords waarmee u te maken hebt. Transacties zorgen ervoor dat eventuele "latere" fouten niet interfereren met "eerdere" dingen die u hebt gedaan. Geen van beiden kan alleen garanderen dat het uiteindelijk goed komt. Maar samen doen ze dat wel.
in de les van morgen:The Joy of Deadlocks.