Khóa bảng ngăn người dùng DB khác ảnh hưởng đến các hàng / bảng bạn đã khóa. Nhưng các khóa, trong và ngoài bản thân, sẽ KHÔNG đảm bảo rằng logic của bạn xuất hiện ở trạng thái nhất quán.
Hãy nghĩ về một hệ thống ngân hàng. Khi bạn thanh toán hóa đơn trực tuyến, có ít nhất hai tài khoản bị ảnh hưởng bởi giao dịch:Tài khoản của bạn, nơi tiền được lấy. Và tài khoản của người nhận, nơi tiền được chuyển vào. Và tài khoản của ngân hàng, nơi họ sẽ vui vẻ gửi tất cả các khoản phí dịch vụ được tính vào giao dịch. Giả sử (như mọi người đều biết ngày nay) rằng các ngân hàng cực kỳ ngu ngốc, giả sử hệ thống của họ hoạt động như thế này:
$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
Giờ đây, không có khóa và không có giao dịch, hệ thống này dễ bị ảnh hưởng bởi các điều kiện đua khác nhau, trong đó lớn nhất là nhiều khoản thanh toán được thực hiện trên tài khoản của bạn hoặc tài khoản của người nhận song song. Trong khi mã của bạn đã được truy xuất số dư của bạn và đang thực hiện lệnh giant_overdraft_fees (), nhưng hoàn toàn có khả năng một số khoản thanh toán khác sẽ chạy song song cùng một loại mã. Họ sẽ truy xuất số dư của bạn (giả sử 100 đô la), thực hiện các giao dịch của họ (lấy 20 đô la bạn đang thanh toán và 30 đô la họ đang vặn bạn với) và bây giờ cả hai đường dẫn mã có hai số dư khác nhau:80 đô la và 70 đô la. Tùy thuộc vào kết thúc cuối cùng, bạn sẽ nhận được một trong hai số dư đó trong tài khoản của mình, thay vì 50 đô la mà bạn đáng lẽ phải có (100 đô la - 20 đô la - 30 đô la). Trong trường hợp này, "lỗi ngân hàng có lợi cho bạn".
Bây giờ, giả sử bạn sử dụng ổ khóa. Thanh toán hóa đơn của bạn (20 đô la) chạm vào đường ống dẫn đầu tiên, vì vậy, nó sẽ thắng và khóa hồ sơ tài khoản của bạn. Giờ đây, bạn đã có quyền sử dụng độc quyền và có thể khấu trừ 20 đô la từ số dư và ghi số dư mới trở lại bình yên ... và tài khoản của bạn kết thúc với 80 đô la như dự kiến. Nhưng ... uh ... Bạn cố gắng cập nhật tài khoản của người nhận, tài khoản của người nhận bị khóa và bị khóa lâu hơn mã cho phép, làm hết thời gian thực hiện giao dịch của bạn ... Chúng tôi đang xử lý các ngân hàng ngu ngốc, vì vậy thay vì gặp lỗi thích hợp xử lý, mã chỉ kéo một exit()
, và 20 đô la của bạn biến mất thành một luồng điện tử. Bây giờ bạn đã hết 20 đô la và bạn vẫn nợ người nhận 20 đô la và điện thoại của bạn sẽ bị thu hồi.
Vì vậy, ... nhập giao dịch. Bạn bắt đầu một giao dịch, bạn ghi nợ tài khoản của mình 20 đô la, bạn cố gắng ghi có cho người nhận 20 đô la ... và một cái gì đó lại nổ tung. Nhưng lần này, thay vì exit()
, mã chỉ có thể thực hiện rollback
và thật tuyệt vời, 20 đô la của bạn được thêm trở lại tài khoản của bạn một cách kỳ diệu.
Cuối cùng, nó kết thúc với điều này:
Các khóa ngăn không cho bất kỳ ai khác can thiệp vào bất kỳ bản ghi cơ sở dữ liệu nào mà bạn đang xử lý. Các giao dịch giữ cho mọi lỗi "sau" không can thiệp vào những việc "trước đó" mà bạn đã thực hiện. Không một mình có thể đảm bảo rằng mọi thứ cuối cùng sẽ diễn ra tốt đẹp. Nhưng cùng nhau, họ làm được.
trong bài học ngày mai:Niềm vui của những bế tắc.