Tôi nghĩ có lẽ tôi muốn thêm nhận xét đó vào câu trả lời trước, về hai câu riêng biệt. Nó đã hơn một năm trước, vì vậy tôi không hoàn toàn chắc chắn nữa.
Truy vấn dựa trên wCTE không thực sự giải quyết được vấn đề mà nó phải giải quyết, nhưng sau khi xem xét lại một năm sau, tôi không thấy khả năng bị mất các bản cập nhật trong phiên bản wCTE.
. bạn cần sử dụng một điểm lưu trữ giữa mỗi thay đổi.)
Phiên bản hai tuyên bố bị mất cập nhật.
Phiên bản sử dụng hai câu lệnh riêng biệt có thể bị mất các bản cập nhật trừ khi ứng dụng kiểm tra số lượng hàng bị ảnh hưởng từ UPDATE
câu lệnh và INSERT
câu lệnh và thử lại nếu cả hai đều bằng không.
Hãy tưởng tượng những gì xảy ra nếu bạn có hai giao dịch READ COMMITTED
riêng lẻ.
- TX1 chạy
UPDATE
(không có hiệu lực)
- TX1 chạy
INSERT
(chèn một hàng)
- TX2 chạy
UPDATE
(không có hiệu lực, hàng được chèn bởi TX1 chưa hiển thị)
- TX1
COMMIT
s.
- TX2 chạy
INSERT
, * có ảnh chụp nhanh mới có thể thấy hàng được TX1 cam kết. Các EXISTS
lợi nhuận khoản đúng, bởi vì bây giờ TX2 có thể nhìn thấy dòng chèn vào bởi TX1.
Vì vậy TX2 không có hiệu lực. Trừ khi ứng dụng kiểm tra số lượng hàng từ bản cập nhật và chèn và thử lại nếu cả hai đều báo cáo các hàng bằng 0, nó sẽ không biết rằng giao dịch không có hiệu lực và sẽ tiếp tục thực hiện.
Cách duy nhất để nó có thể kiểm tra số lượng hàng bị ảnh hưởng là chạy nó dưới dạng hai câu lệnh riêng biệt thay vì một câu lệnh đa hoặc sử dụng một thủ tục.
Bạn có thể sử dụng SERIALIZABLE
cách ly, nhưng bạn vẫn sẽ cần một vòng lặp thử lại để xử lý các lỗi nối tiếp.
Phiên bản wCTE bảo vệ chống lại sự cố cập nhật bị mất vì INSERT
điều kiện là liệu điều đó có UPDATE
ảnh hưởng đến bất kỳ hàng nào không, thay vì trên một truy vấn riêng biệt.
WCTE không loại bỏ các vi phạm duy nhất
Phiên bản CTE có thể ghi vẫn không phải là một phiên bản đáng tin cậy.
Hãy xem xét hai giao dịch chạy đồng thời.
Cả hai đều thực hiện mệnh đề GIÁ TRỊ.
Bây giờ cả hai thực hiện UPDATE
phần. Vì không có hàng nào khớp với UPDATE
mệnh đề s where, cả hai đều trả về một tập kết quả trống từ bản cập nhật và không thay đổi.
Bây giờ cả hai chạy INSERT
phần. Vì các UPDATE
hàng 0 được trả về cho cả hai truy vấn, cả hai đều cố gắng vào INSERT
hàng.
Một người thành công. Một người ném một vi phạm độc đáo và hủy bỏ.
Điều này không gây lo ngại về việc mất dữ liệu miễn là ứng dụng kiểm tra kết quả lỗi từ các truy vấn của nó (tức là bất kỳ ứng dụng được viết nào) và thử lại, nhưng nó làm cho giải pháp không tốt hơn các phiên bản hai câu lệnh hiện có. Nó không loại bỏ sự cần thiết của một vòng lặp thử lại.
Ưu điểm mà wCTE cung cấp so với phiên bản hai câu lệnh hiện tại là nó sử dụng đầu ra của UPDATE
quyết định để INSERT
thay thế, thay vì sử dụng một truy vấn riêng đối với bảng. Đó là một phần tối ưu hóa, nhưng nó một phần bảo vệ chống lại sự cố với phiên bản hai câu lệnh gây ra các bản cập nhật bị mất; xem bên dưới.
Bạn có thể chạy wCTE một SERIALIZABLE
cách cô lập, nhưng sau đó bạn sẽ chỉ nhận được các lỗi nối tiếp thay vì các vi phạm duy nhất. Nó sẽ không thay đổi sự cần thiết của một vòng lặp thử lại.
WCTE dường như không dễ bị cập nhật
Nhận xét của tôi cho thấy giải pháp này có thể dẫn đến mất cập nhật, nhưng khi xem xét tôi nghĩ rằng tôi có thể đã nhầm.
Cách đây hơn một năm và tôi không thể nhớ lại các trường hợp chính xác, nhưng tôi nghĩ có lẽ tôi đã bỏ lỡ thực tế là các chỉ mục duy nhất có ngoại lệ một phần từ quy tắc hiển thị giao dịch để cho phép một giao dịch chèn chờ một giao dịch khác chèn hoặc cuộn trở lại trước khi tiến hành.
Hoặc có lẽ tôi đã bỏ lỡ một thực tế rằng INSERT
trong wCTE là có điều kiện về việc liệu các UPDATE
hàng có bị ảnh hưởng hay không, không phải là liệu hàng ứng cử viên có tồn tại trong bảng hay không.
Xung đột INSERT
s trên một chỉ mục duy nhất chờ cam kết / rollback
Nói rằng một bản sao của truy vấn chạy, chèn một hàng. Sự thay đổi chưa được cam kết. Bộ dữ liệu mới tồn tại trong heap và chỉ mục duy nhất, nhưng nó chưa hiển thị cho các giao dịch khác, bất kể mức độ cô lập.
Bây giờ một bản sao khác của truy vấn chạy. Hàng được chèn chưa hiển thị vì bản sao đầu tiên chưa được cam kết, vì vậy bản cập nhật không khớp với bất cứ thứ gì. Truy vấn sẽ tiếp tục thử chèn, sẽ thấy rằng một giao dịch đang thực hiện khác đang chèn cùng khóa đó và sẽ chặn chờ giao dịch đó được cam kết hoặc khôi phục .
Nếu giao dịch đầu tiên được thực hiện, giao dịch thứ hai sẽ thất bại với một vi phạm duy nhất, theo các điều trên. Nếu giao dịch đầu tiên quay trở lại thì giao dịch thứ hai sẽ tiến hành thay thế.
Việc INSERT
phụ thuộc vào số lượng hàng UPDATE
bảo vệ chống lại các cập nhật bị mất
Không giống như trong trường hợp hai tuyên bố, tôi không nghĩ rằng wCTE dễ bị mất các bản cập nhật.
Nếu UPDATE
không có hiệu lực, ý INSERT
chí sẽ luôn luôn chạy, bởi vì nó hoàn toàn có điều kiện về việc liệu UPDATE
đã làm bất cứ điều gì, không phải ở trạng thái bảng bên ngoài. Vì vậy, nó vẫn có thể thất bại với một vi phạm duy nhất, nhưng nó không thể âm thầm không có bất kỳ ảnh hưởng nào và mất hoàn toàn bản cập nhật.