Thay vì FOR UPDATE
sử dụng LOCK IN SHARE MODE
. FOR UPDATE
cũng ngăn các giao dịch khác đọc hàng. LOCK IN SHARE MODE
cho phép đọc, nhưng ngăn cập nhật.
Tham khảo: Hướng dẫn sử dụng MySQL
------ buổi 1
START TRANSACTION;
SELECT * FROM test WHERE t=1 LOCK IN SHARE MODE;
UPDATE test SET NAME='irfandd' WHERE t=2;
COMMIT;
----- phiên 2 (không bị chặn nữa :))
START TRANSACTION;
UPDATE test SET NAME='irfandd' WHERE t=4;
COMMIT;
Cập nhật:
Nhận thấy rằng bảng không có chỉ mục trên t
, Tôi có lời giải thích sau:
Đầu tiên, giao dịch T1 khóa hàng 1 trong SELECT * FROM test WHERE t=1 FOR UPDATE
Tiếp theo, giao dịch T2 cố gắng thực hiện UPDATE test SET NAME='irfandd' WHERE t=4
. Để tìm ra (các) hàng bị ảnh hưởng, nó cần phải quét tất cả các hàng, bao gồm cả hàng 1 . Nhưng điều đó đã bị khóa, vì vậy T2 phải đợi cho đến khi T1 kết thúc. Nếu có bất kỳ loại chỉ mục nào, hãy WHERE t=4
có thể sử dụng chỉ mục để quyết định xem hàng 1 chứa t=4
hoặc không, vì vậy không cần đợi.
Tùy chọn 1: thêm chỉ mục trên test.t
để cập nhật của bạn có thể sử dụng nó.
Tùy chọn 2: sử dụng LOCK IN SHARE MODE
, mục đích chỉ để đặt khóa đọc. Rất tiếc, tùy chọn này tạo ra một bế tắc. Điều thú vị là giao dịch T2 thực hiện (cập nhật hàng 4) và T1 không thành công (cập nhật hàng 2). Có vẻ như T1 đã khóa hàng 4 cũng như vì T2 sửa đổi nó, T1 không thành công do mức cô lập giao dịch ( REPEATABLE READ theo mặc định
). Giải pháp cuối cùng sẽ là sử dụng Mức cách ly giao dịch , sử dụng READ UNCOMMITTED
hoặc READ COMMITTED
mức giao dịch.
Đơn giản nhất là Tùy chọn 1 , IMHO, nhưng tùy thuộc vào khả năng của bạn.