TL; DR: Câu hỏi dưới đây rút ra: Khi chèn một hàng, có một cửa sổ cơ hội giữa việc tạo ra một Identity
giá trị mới và khóa của khóa hàng tương ứng trong chỉ mục được nhóm, trong đó người quan sát bên ngoài có thể thấy một cái mới hơn Identity
giá trị được chèn bởi một giao dịch đồng thời? (Trong Máy chủ SQL.)
Phiên bản chi tiết
Tôi có một bảng SQL Server với một Identity
cột được gọi CheckpointSequence
, đó là khóa của chỉ mục được nhóm của bảng (cũng có một số chỉ mục không bao gồm bổ sung). Các hàng được chèn vào bảng bởi một số quy trình và luồng đồng thời (ở mức cô lập READ COMMITTED
và không có IDENTITY_INSERT
). Đồng thời, có các quy trình đọc định kỳ các hàng từ chỉ mục được nhóm, được sắp xếp theo CheckpointSequence
cột đó (cũng ở mức cô lập READ COMMITTED
, với READ COMMITTED SNAPSHOT
tùy chọn bị tắt).
Tôi hiện đang dựa vào thực tế là các quá trình đọc không bao giờ có thể "bỏ qua" một điểm kiểm tra. Câu hỏi của tôi là: Tôi có thể dựa vào tài sản này? Và nếu không, tôi có thể làm gì để biến nó thành sự thật?
Ví dụ: Khi các hàng có giá trị nhận dạng 1, 2, 3, 4 và 5 được chèn, người đọc không được nhìn thấy hàng có giá trị 5 trước khi nhìn thấy hàng có giá trị 4. Các thử nghiệm cho thấy truy vấn có chứa ORDER BY CheckpointSequence
mệnh đề ( và một WHERE CheckpointSequence > -1
mệnh đề), đáng tin cậy chặn bất cứ khi nào hàng 4 được đọc, nhưng chưa được cam kết, ngay cả khi hàng 5 đã được cam kết.
Tôi tin rằng ít nhất trên lý thuyết, có thể có một điều kiện chủng tộc ở đây có thể khiến giả định này bị phá vỡ. Thật không may, tài liệu về Identity
không nói nhiều về cách Identity
hoạt động trong bối cảnh của nhiều giao dịch đồng thời, nó chỉ nói "Mỗi giá trị mới được tạo dựa trên hạt giống & gia tăng hiện tại." và "Mỗi giá trị mới cho một giao dịch cụ thể khác với các giao dịch đồng thời khác trên bảng." ( MSDN )
Lý do của tôi là, nó phải hoạt động bằng cách nào đó như thế này:
- Một giao dịch được bắt đầu (rõ ràng hoặc ngầm).
- Một giá trị nhận dạng (X) được tạo ra.
- Khóa hàng tương ứng được lấy trên chỉ mục được phân cụm dựa trên giá trị nhận dạng (trừ khi khóa leo thang khóa, trong trường hợp đó toàn bộ bảng bị khóa).
- Hàng được chèn.
- Giao dịch được cam kết (có thể khá nhiều thời gian sau đó), vì vậy khóa được gỡ bỏ một lần nữa.
Tôi nghĩ rằng giữa bước 2 và 3, có một cửa sổ rất nhỏ trong đó
- một phiên đồng thời có thể tạo ra giá trị nhận dạng tiếp theo (X + 1) và thực hiện tất cả các bước còn lại,
- do đó cho phép người đọc đến chính xác tại thời điểm đó để đọc giá trị X + 1, thiếu giá trị của X.
Tất nhiên, xác suất của điều này có vẻ cực kỳ thấp; nhưng vẫn có thể xảy ra Hay nó có thể?
(Nếu bạn quan tâm đến bối cảnh: Đây là việc triển khai Công cụ bền bỉ SQL của NEventStore . NEventStore triển khai một cửa hàng sự kiện chỉ có phụ lục trong đó mọi sự kiện đều có số thứ tự điểm kiểm tra tăng dần mới. Khách hàng đọc các sự kiện từ cửa hàng sự kiện được sắp xếp theo điểm kiểm tra. Để thực hiện các tính toán của tất cả các loại. Một khi một sự kiện với điểm kiểm tra X đã được xử lý, khách hàng chỉ xem xét các sự kiện "mới hơn", tức là các sự kiện có điểm kiểm tra X + 1 trở lên. Do đó, điều quan trọng là các sự kiện không bao giờ được bỏ qua, vì chúng sẽ không bao giờ được xem xét lại. Hiện tại tôi đang cố gắng xác định xem việc Identity
triển khai điểm kiểm tra dựa trên cơ sở có đáp ứng yêu cầu này không. Đây là các câu lệnh SQL chính xác được sử dụng : Schema , Truy vấn của nhà văn ,Truy vấn của độc giả .)
Nếu tôi đúng và tình huống được mô tả ở trên có thể phát sinh, tôi chỉ có thể thấy hai tùy chọn xử lý chúng, cả hai đều không thỏa đáng:
- Khi thấy giá trị chuỗi điểm kiểm tra X + 1 trước khi thấy X, hãy bỏ X + 1 và thử lại sau. Tuy nhiên, vì
Identity
tất nhiên có thể tạo ra các khoảng trống (ví dụ: khi giao dịch được khôi phục), X có thể không bao giờ đến. - Vì vậy, cùng một cách tiếp cận, nhưng chấp nhận khoảng cách sau n mili giây. Tuy nhiên, giá trị nào của n tôi nên giả sử?
Còn ý tưởng nào hay hơn không?