Заключването на таблици не позволява на други потребители на DB да повлияят на редовете/таблиците, които сте заключили. Но заключванията сами по себе си НЯМА да гарантират, че логиката ви ще излезе в последователно състояние.
Помислете за банкова система. Когато плащате сметка онлайн, има поне две сметки, засегнати от транзакцията:Вашата сметка, от която се вземат парите. И сметката на получателя, в която се превеждат парите. И банковата сметка, в която с радост ще депозират всички такси за обслужване, начислени по транзакцията. Като се има предвид (както всички знаят тези дни), че банките са изключително глупави, да кажем, че тяхната система работи по следния начин:
$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
Сега, без заключвания и транзакции, тази система е уязвима към различни условия на състезание, най-големият от които е множеството плащания, извършвани във вашата сметка или сметката на получателя паралелно. Докато вашият код извлича баланса ви и извършва huge_overdraft_fees() и какво ли още не, е напълно възможно някое друго плащане да изпълнява същия тип код паралелно. Те ще извлекат баланса ви (да речем, $100), ще извършат транзакциите си (извадят $20, които плащате, и $30, с които ви прецакват), и сега и двата пътя на кода имат два различни баланса:$80 и $70. В зависимост от това кои завършват последни, в крайна сметка ще получите някое от тези две салда в акаунта си, вместо $50, с които би трябвало да завършите ($100 - $20 - $30). В този случай „банкова грешка във ваша полза“.
Сега да кажем, че използвате ключалки. Плащането на сметката ви ($20) излиза първо, така че печели и заключва записа на акаунта ви. Сега имате ексклузивна употреба и можете да приспаднете 20-те долара от баланса и спокойно да запишете новото салдо... и акаунтът ви завършва с 80 долара, както се очаква. Но... ох... Опитвате се да отидете да актуализирате акаунта на получателя и той е заключен и заключен по-дълго, отколкото позволява кодът, изтича времето на вашата транзакция... Ние имаме работа с глупави банки, така че вместо да имаме правилна грешка обработка, кодът просто изтегля exit()
, и вашите $20 изчезват в струйка от електрони. Сега нямате $20 и все още дължите $20 на приемника, а телефонът ви ще бъде иззет.
Така че... въведете транзакции. Започвате транзакция, дебитирате сметката си $20, опитвате се да кредитирате получателя с $20... и нещо отново се взривява. Но този път вместо exit()
, кодът може просто да направи rollback
, и пуф, вашите $20 се добавят магически обратно към вашия акаунт.
В крайна сметка всичко се свежда до това:
Заключването предпазва всеки друг от намеса в записи на базата данни, с които работите. Транзакциите предпазват всички „по-късни“ грешки от намеса в „по-ранните“ неща, които сте направили. Нито един от тях сам по себе си не може да гарантира, че в крайна сметка нещата ще се оправят. Но заедно го правят.
в утрешния урок:Радостта от безизходица.