Từ quan điểm lý thuyết thuần túy, có vẻ như bạn đang không khóa đúng hàng (điều kiện trong câu lệnh đầu tiên khác với trong câu lệnh cập nhật; ngoài ra bạn chỉ khóa một hàng vì LIMIT 1
, trong khi bạn có thể cập nhật nhiều hàng hơn sau này).
Hãy thử điều này:
START TRANSACTION;
SELECT v_id FROM v_ext WHERE username IS NULL AND v_id=yyy FOR UPDATE;
UPDATE v_ext SET username=xxx WHERE v_id=yyy;
COMMIT;
[sửa]
Đối với lý do bế tắc của bạn, đây là câu trả lời có thể xảy ra ( từ hướng dẫn sử dụng ):
Không có chỉ mục, SELECT ... FOR UPDATE
câu lệnh có khả năng khóa toàn bộ bảng, trong khi với một chỉ mục, nó chỉ khóa một số hàng. Bởi vì bạn không khóa các hàng bên phải trong câu lệnh đầu tiên, một khóa bổ sung được nhận trong câu lệnh thứ hai.
Rõ ràng là không thể xảy ra bế tắc nếu toàn bộ bảng bị khóa (tức là không có chỉ mục). Một bế tắc chắc chắn có thể xảy ra trong lần thiết lập thứ hai.