Về các vấn đề đồng thời, bạn có một 'dễ dàng' cách để ngăn chặn bất kỳ sự cố đồng thời nào trong phương pháp thứ 2, bên trong giao dịch của bạn, hãy thực hiện một lựa chọn trên dòng bài viết (For update
bây giờ là ẩn). Bất kỳ phụ trang đồng thời nào trên cùng một bài viết sẽ không thể lấy được cùng một khóa này và sẽ đợi bạn.
Với các mức cách ly mặc định mới, thậm chí không sử dụng mức tuần tự hóa trong giao dịch, bạn sẽ không thấy bất kỳ chèn đồng thời nào trên bảng bỏ phiếu cho đến khi kết thúc giao dịch của mình. Vì vậy, SUM của bạn phải mạch lạc hoặc trông giống như mạch lạc . Nhưng nếu một giao dịch đồng thời chèn một phiếu bầu trên cùng một bài viết và cam kết trước bạn (và bài viết thứ hai này không thấy phụ trang của bạn), thì giao dịch cuối cùng để cam kết sẽ ghi đè lên bộ đếm và bạn sẽ mất 1 phiếu bầu. Vì vậy, hãy thực hiện khóa hàng đối với bài viết bằng cách sử dụng một lựa chọn trước (và thực hiện công việc của bạn trong một giao dịch, tất nhiên). Thật dễ dàng để kiểm tra, mở 2 phiên tương tác trên MySQL và bắt đầu giao dịch với BEGIN.
Nếu bạn sử dụng trình kích hoạt, bạn đang tham gia một giao dịch theo mặc định. Nhưng tôi nghĩ bạn cũng nên thực hiện việc chọn trên bảng bài viết để tạo một khóa hàng ngầm cho các trình kích hoạt đồng thời đang chạy (khó kiểm tra hơn).
- Đừng quên xóa các trình kích hoạt.
- Đừng quên các trình kích hoạt cập nhật.
- Nếu bạn không sử dụng trình kích hoạt và mã ở lại, hãy cẩn thận với mọi truy vấn chèn / xóa / cập nhật trên phiếu bầu nên thực hiện khóa hàng trên bài viết tương ứng trước đó trong giao dịch. Không khó để quên một người.
Điểm cuối cùng:thực hiện các giao dịch khó hơn, trước khi bắt đầu sử dụng giao dịch:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
Bằng cách này, bạn không cần khóa hàng trên các bài báo, MySQL sẽ phát hiện ra rằng một lần viết tiềm năng trên cùng một hàng xảy ra và sẽ chặn các giao dịch khác cho đến khi bạn hoàn thành. Nhưng không sử dụng thứ gì đó bạn đã tính toán từ yêu cầu trước đó . Truy vấn cập nhật sẽ chờ phát hành khóa trên các bài báo, khi khóa được phát hành bởi giao dịch đầu tiên COMMIT
tính toán của SUM
nên được thực hiện lại để đếm. Vì vậy, truy vấn cập nhật phải chứa SUM
hoặc bổ sung.
update articles set nb_votes=(SELECT count(*) from vote) where id=2;
Và ở đây, bạn sẽ thấy rằng MySQL rất thông minh, một điểm bế tắc được phát hiện nếu 2 giao dịch đang cố gắng thực hiện điều này trong khi việc chèn được thực hiện đồng thời. Trong các cấp độ tuần tự hóa, tôi không tìm thấy cách nào để lấy sai giá trị với:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN;
insert into vote (...
update articles set nb_votes=(
SELECT count(*) from vote where article_id=xx
) where id=XX;
COMMIT;
Nhưng hãy sẵn sàng xử lý giao dịch vi phạm mà bạn phải thực hiện lại.