Theo số UPDATE
documentation, UPDATE
luôn mua một khóa độc quyền trên toàn bộ bảng. Tuy nhiên, tôi tự hỏi nếu khóa độc quyền được mua trước khi các hàng được cập nhật được xác định hoặc chỉ ngay trước khi cập nhật thực tế.Giao dịch chỉ cập nhật một bảng đơn luôn bị cô lập?
vấn đề cụ thể của tôi là tôi có một lồng nhau SELECT
trong UPDATE
của tôi như thế này:
UPDATE Tasks
SET Status = 'Active'
WHERE Id = (SELECT TOP 1 Id
FROM Tasks
WHERE Type = 1
AND (SELECT COUNT(*)
FROM Tasks
WHERE Status = 'Active') = 0
ORDER BY Id)
Bây giờ tôi tự hỏi liệu nó có thực sự được đảm bảo rằng có đúng một nhiệm vụ với Status = 'Active'
sau đó nếu song song các tuyên bố tương tự có thể được thực hiện với một Loại khác:
UPDATE Tasks
SET Status = 'Active'
WHERE Id = (SELECT TOP 1 Id
FROM Tasks
WHERE Type = 2 -- <== The only difference
AND (SELECT COUNT(*)
FROM Tasks
WHERE Status = 'Active') = 0
ORDER BY Id)
Nếu cả hai câu lệnh thay đổi hàng sẽ được xác định trước khi khóa được mua, tôi có thể kết thúc với hai nhiệm vụ hoạt động mà tôi phải ngăn chặn.
Nếu đúng như vậy, làm cách nào để ngăn chặn? Tôi có thể ngăn chặn nó mà không đặt mức giao dịch thành SERIALIZABLE
hoặc gây rối với các gợi ý khóa không?
Từ câu trả lời cho Is a single SQL Server statement atomic and consistent? Tôi đã học được rằng vấn đề phát sinh khi lồng nhau SELECT
truy cập vào một bảng khác. Tuy nhiên, tôi không chắc liệu tôi có quan tâm đến vấn đề này hay không nếu chỉ có bảng cập nhật có liên quan.
tài liệu Đó là sai anyway. Cập nhật thường sẽ không khóa toàn bộ bảng. –
Hm, ok, cảm ơn. Nhưng tôi tìm tài liệu chính xác ở đâu? – lex82
Tài liệu không thực sự nói rằng 'UPDATE' khóa toàn bộ bảng. Nó nói rằng nó mua lại một khóa độc quyền, nhưng một khóa độc quyền không có trên toàn bộ bảng. –