Blokowanie tabel zapobiega wpływowi innych użytkowników bazy danych na zablokowane wiersze / tabele. Ale blokady same w sobie NIE zapewnią, że logika pojawi się w spójnym stanie.
Pomyśl o systemie bankowym. Kiedy płacisz rachunek online, transakcja ma wpływ na co najmniej dwa konta: Twoje konto, z którego pobierane są pieniądze. Oraz konto odbiorcy, na które wpłacane są pieniądze. I konto w banku, na które z radością wpłacą wszystkie opłaty serwisowe naliczone przy transakcji. Biorąc pod uwagę (jak wszyscy wiedzą w dzisiejszych czasach), że banki są wyjątkowo głupie, powiedzmy, że ich system działa tak:
$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
Teraz, bez blokad i transakcji, system ten jest podatny na różne warunki wyścigu, z których największym jest wielokrotne dokonywanie płatności na Twoim koncie lub równolegle na konto odbiorcy. Podczas gdy twój kod ma odzyskane saldo i wykonuje ogromne_przedaż_opłat () i tak dalej, jest całkowicie możliwe, że jakaś inna płatność będzie uruchamiać równolegle ten sam typ kodu. Odzyskają Twoje saldo (powiedzmy 100 USD), przeprowadzą transakcje (wyjmą 20 USD, które płacisz, i 30 USD, z którymi cię oszukują), a teraz obie ścieżki kodu mają dwa różne salda: 80 USD i 70 $. W zależności od tego, który z nich zakończy się jako ostatni, otrzymasz na swoim koncie jedno z dwóch sald, zamiast 50 USD, które powinieneś otrzymać (100 USD - 20 USD - 30 USD). W tym przypadku „błąd banku na Twoją korzyść”
Powiedzmy, że używasz zamków. Twoja płatność za rachunek (20 USD) trafia jako pierwsza, więc wygrywa i blokuje rekord Twojego konta. Teraz masz wyłączne zastosowanie i możesz odliczyć 20 $ z salda i w spokoju zapisać nowe saldo ... a Twoje konto kończy się 80 $ zgodnie z oczekiwaniami. Ale ... uhoh ... Próbujesz zaktualizować konto odbiorcy, a jest ono zablokowane i zablokowane dłużej niż pozwala na to kod, przekroczenie limitu czasu transakcji ... Mamy do czynienia z głupimi bankami, więc zamiast mieć właściwy błąd obsługa, kod po prostu ciągnie an exit()
, a twoje 20 $ znika w pęczek elektronów. Teraz straciłeś 20 $, a nadal jesteś winien 20 $ odbiorcy, a Twój telefon zostaje przejęty.
Więc ... wprowadź transakcje. Rozpoczynasz transakcję, obciążasz konto 20 $, próbujesz zasilić odbiorcę 20 $ ... i znowu coś wybucha. Ale tym razem, zamiast exit()
, kod może po prostu zrobić rollback
, i poof, twoje 20 $ zostanie magicznie dodane z powrotem do twojego konta.
W końcu sprowadza się to do tego:
Blokady uniemożliwiają innym ingerowanie w jakiekolwiek rekordy bazy danych, z którymi masz do czynienia. Dzięki transakcjom wszelkie „późniejsze” błędy nie kolidują z „wcześniejszymi” czynnościami, które wykonałeś. Żaden z nich sam nie gwarantuje, że wszystko pójdzie dobrze. Ale razem to robią.
w jutrzejszej lekcji: Radość z impasu.