LOCK IN SHARE MODE sẽ cho phép luồng thứ 2 đọc giá trị, nhưng giá trị thực sẽ là luồng trước khi truy vấn (đọc được cam kết) hoặc trước khi giao dịch (đọc có thể lặp lại) được bắt đầu (vì MySQL sử dụng đa phiên bản; và những gì phải được nhìn thấy bởi giao dịch thứ hai được xác định bởi mức cô lập). Vì vậy, nếu giao dịch đầu tiên không được cam kết tại thời điểm đọc, giá trị cũ sẽ được đọc.
Trong tình huống của bạn, tốt nhất nên có 1 giao dịch khóa bản ghi với lựa chọn để cập nhật, một giao dịch khác hoạt động trên bản ghi và khi commit / rollback, giao dịch thứ ba sẽ mở khóa bản ghi.
Giao dịch luồng thứ hai với lựa chọn để cập nhật sẽ đợi giao dịch đầu tiên hoàn thành, sau đó sẽ đọc giá trị thực và sẽ quyết định không tiếp tục với các giao dịch khác, nhưng để thông báo cho người dùng rằng bản ghi đã bị khóa.
Để tránh bế tắc, hãy đảm bảo rằng bạn đang thực hiện select for update
sử dụng một chỉ mục duy nhất.
Mã mẫu:
connection.setautocommit(false);
//transaction-1
PreparedStatement ps1 = "Select locked from tableName for update where id="key" and locked=false);
ps1.executeQuery();
//transaction 2
PreparedStatement ps2 = "Update tableName set locked=true where id="key";
ps2.executeUpdate();
connection.setautocommit(true); // here we allow other transactions / threads to see the new value
connection.setautocommit(false);
//transaction 3
PreparedStatement ps3 = "Update tableName set aField="Sthg" where id="key" And date="D" and topic="T";
ps3.executeUpdate();
// probably more queries
// reset locked to false
PreparedStatement ps4 = "Update tableName set locked=false where id="key";
ps4.executeUpdate();
//commit
connection.setautocommit(true);