Tôi đã đề cập đến việc NOLOCK mang lại kết quả ngẫu nhiên như thế nào khi bạn truy vấn dữ liệu đang thay đổi, và đó là một minh chứng rất mạnh mẽ để cho những người nghĩ rằng NOLOCK an toàn khi sử dụng trong môi trường production thấy. Tuy nhiên, tôi đã nhận được câu hỏi từ một vài người dùng:
Nhưng tôi đang truy vấn dữ liệu không thay đổi – chắc chắn là CÁC hàng KHÁC trong bảng đang thay đổi, nhưng không phải các hàng tôi đang truy vấn. NOLOCK chẳng phải vẫn ổn nếu tôi truy vấn các hàng ổn định sao?
Không, hoàn toàn không. Hãy lấy bất kỳ cơ sở dữ liệu Stack Overflow nào, và bắt đầu với truy vấn từ bài viết trước – ngoại trừ lần này chúng ta sẽ sửa đổi nó để cập nhật một số người dùng và truy vấn những người khác. Hãy bắt đầu bằng việc xóa các chỉ mục (indexes) của bạn để có được kết quả nhất quán:
1 | EXEC DropIndexes; |
Một trong những DisplayNames phổ biến hơn là Alex. Trong một cửa sổ, tôi sẽ lấy số lượng người tên Alex:
Transact-SQL
1234 | SELECT COUNT(*) FROM dbo.Users WITH (NOLOCK)WHERE DisplayName = 'alex';GO 20 |
Và trong cửa sổ kia, tôi sẽ thiết lập vị trí và trang web của mọi người – NGOẠI TRỪ những người tên Alex, những người mà tôi sẽ không đụng đến:
Transact-SQL
123456 | BEGIN TRANUPDATE dbo.Users SET Location = N'The Derek Zoolander School for Kids Who Can''t Read Good and Want to Do Other Stuff Good Too', WebsiteUrl = N'https://www.youtube.com/watch?v=NQ-8IuUkJJc' WHERE DisplayName <> 'alex';GO |
Hãy xem thảm họa diễn ra:
NOLOCK mang lại cho bạn kết quả ngẫu nhiên.
Số lượng người dùng tên Alex dường như liên tục thay đổi – MẶC DÙ TÔI KHÔNG CẬP NHẬT NHỮNG HÀNG ĐÓ! Lý do: vị trí các hàng của Alex có thể bị di chuyển bởi những thứ đang xảy ra với các hàng khác.
Tôi không thể nhấn mạnh điều này đủ: với NOLOCK, bạn có thể:
Nhìn thấy các hàng hai lần
Bỏ qua hoàn toàn các hàng
Nhìn thấy dữ liệu chưa bao giờ được commit
Và khiến truy vấn của bạn thất bại với một lỗi
Nếu bạn thấy ổn với điều đó, tuyệt – NOLOCK dành cho bạn. Nếu không, đã đến lúc xem xét các cách khác để đạt được hiệu suất bạn muốn trong khi vẫn có được độ chính xác dữ liệu mà người dùng của bạn yêu cầu.
Nếu bạn muốn chạy lại bản demo nhiều lần, bạn sẽ cần phải xây dựng lại bảng giữa các lần thực hiện:
1 | ALTER TABLE dbo.Users REBUILD; |