Blokowanie tabel uniemożliwia innym użytkownikom bazy danych wpływanie na zablokowane wiersze/tabele. Ale blokady same w sobie NIE zapewnią spójnego stanu logiki.
Pomyśl o systemie bankowym. Kiedy płacisz rachunek online, są co najmniej dwa konta objęte transakcją:Twoje konto, z którego pobierane są pieniądze. Oraz konto odbiorcy, na które przelewane są pieniądze. I konto w banku, na które z radością wpłaci wszystkie opłaty serwisowe pobierane od 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 na koncie odbiorcy równolegle. Podczas gdy Twój kod ma odzyskane saldo i wykonuje funkcję huge_overdraft_fees() i tak dalej, jest całkowicie możliwe, że jakaś inna płatność będzie równolegle uruchamiać ten sam typ kodu. Odzyskają twoje saldo (powiedzmy 100 dolarów), wykonają swoje transakcje (wyjmą 20 dolarów, które płacisz, i 30 dolarów, którymi cię wkręcają), a teraz obie ścieżki kodu mają dwa różne salda:80 dolarów i 70 dolarów. W zależności od tego, które z nich zakończy się jako ostatnie, otrzymasz jedno z tych dwóch sald na swoim koncie, zamiast 50 USD, które powinieneś mieć (100 USD - 20 USD - 30 USD). W tym przypadku „błąd banku na twoją korzyść”.
Załóżmy, ż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 użycie i możesz odjąć 20 USD od salda i w spokoju odpisać nowe saldo ... a Twoje konto zakończy się z 80 USD zgodnie z oczekiwaniami. Ale... ohh... Próbujesz zaktualizować konto odbiorcy i jest ono zablokowane i zablokowane dłużej niż pozwala na to kod, limit czasu transakcji... Mamy do czynienia z głupimi bankami, więc zamiast poprawnego błędu obsługi, kod po prostu ściąga exit()
, a twoje 20 dolarów znika w kłębku elektronów. Teraz tracisz 20 dolarów i nadal jesteś winien 20 dolarów odbiorcy, a twój telefon zostaje przejęty.
Więc... wprowadź transakcje. Rozpoczynasz transakcję, obciążasz swoje konto 20 zł, próbujesz zasilić odbiorcę kwotą 20 zł... i znowu coś wybucha. Ale tym razem zamiast exit()
, kod może po prostu wykonać rollback
, i puf, twoje 20 $ zostanie magicznie dodane z powrotem do twojego konta.
W końcu sprowadza się to do tego:
Blokady uniemożliwiają innym ingerowanie w rekordy bazy danych, z którymi masz do czynienia. Transakcje sprawiają, że wszelkie „późniejsze” błędy nie zakłócają „wcześniejszych” czynności. Żaden sam nie może zagwarantować, że wszystko w końcu ułoży się dobrze. Ale razem robią.
w jutrzejszej lekcji:Radość impasów.