Giả sử bạn có đoạn mã sau (xin vui lòng bỏ qua rằng nó quá tệ):
BEGIN TRAN;
DECLARE @id int
SELECT @id = id + 1 FROM TableA;
UPDATE TableA SET id = @id; --TableA must have only one row, apparently!
COMMIT TRAN;
-- @id is returned to the client or used somewhere else
Trước mắt tôi, đây KHÔNG phải là quản lý đồng thời đúng cách. Chỉ vì bạn có một giao dịch không có nghĩa là người khác sẽ không đọc cùng giá trị mà bạn đã làm trước khi bạn nhận được tuyên bố cập nhật của mình.
Bây giờ, để lại mã như hiện tại (tôi nhận ra điều này được xử lý tốt hơn dưới dạng một câu lệnh hoặc thậm chí tốt hơn bằng cách sử dụng cột tự động / nhận dạng), những cách chắc chắn để làm cho nó xử lý đồng thời đúng cách và ngăn chặn các điều kiện cuộc đua cho phép hai khách hàng có được cùng một giá trị id?
Tôi khá chắc chắn rằng việc thêm một WITH (UPDLOCK, HOLDLOCK)
vào CHỌN sẽ thực hiện thủ thuật. Mức cô lập giao dịch SERIALIZABLE dường như cũng hoạt động vì nó từ chối bất kỳ ai khác đọc những gì bạn đã làm cho đến khi tran kết thúc ( CẬP NHẬT : điều này là sai. Xem câu trả lời của Martin). Điều đó có đúng không? Cả hai sẽ làm việc tốt như nhau? Là một trong những ưa thích hơn khác?
Hãy tưởng tượng làm một cái gì đó hợp pháp hơn một bản cập nhật ID - một số tính toán dựa trên bài đọc mà bạn cần cập nhật. Có thể có nhiều bảng liên quan, một số bảng bạn sẽ viết và những bảng khác bạn sẽ không viết. Thực hành tốt nhất ở đây là gì?
Đã viết câu hỏi này, tôi nghĩ rằng các gợi ý khóa là tốt hơn bởi vì sau đó bạn chỉ khóa các bảng bạn cần, nhưng tôi đánh giá cao đầu vào của bất kỳ ai.
Tái bút: Không, tôi không biết câu trả lời hay nhất và thực sự muốn hiểu rõ hơn! :)
update
có thể dựa trên dữ liệu quá cũ không? Nếu sau này, bạn có thể sử dụngrowversion
cột để kiểm tra xem hàng cần cập nhật đã không bị thay đổi kể từ khi nó được đọc.