Chỉnh sửa: Như @MaxVernon chỉ ra, sau đây không phải là một gợi ý để sử dụng NOLOCK , và tôi rất nên đề cập đến việc thiết lập mức độ giao dịch READ UNCOMMITED
và để ý nghĩa tiêu cực đứng ở vị trí đó hơn là đưa NOLOCK
ra ở vị trí đầu tiên. Vì vậy, như được đăng ban đầu:
Nhanh chóng và đơn giản là "Có, truy vấn đầu tiên sẽ chặn truy vấn thứ hai trừ khi một gợi ý chỉ mục cụ thể được chỉ định ( NOLOCK , đôi khi được gọi là" đọc bẩn ") hoặc mức cô lập giao dịch của truy vấn thứ hai được đặt thành READ UNCOMMITED
(hoạt động giống hệt nhau), không nó không."
Để trả lời cho chi tiết bổ sung được cung cấp trong câu hỏi đòi hỏi phải bao gồm một WITH
mệnh đề trên phần hai SELECT
, loại trừ lẫn nhau hoặc nếu không, các tương tác giữa hai truy vấn sẽ phần lớn giống nhau.
IF NOT EXISTS ( SELECT 1
FROM sys.objects
WHERE name = 'Foo'
AND type = 'U' )
BEGIN
--DROP TABLE dbo.Foo;
CREATE TABLE dbo.Foo
(
Foo_PK BIGINT IDENTITY( 1, 1 ) NOT NULL,
PRIMARY KEY ( Foo_PK ),
Bar BIT,
x BIT,
y BIT,
z BIT
);
CREATE NONCLUSTERED INDEX IX_Foo_x
ON dbo.Foo ( x );
INSERT INTO dbo.Foo ( Bar, x, y, z )
VALUES ( 1, 1, 1, 1 ), ( 0, 0, 0, 0 );
END;
GO
BEGIN TRANSACTION;
UPDATE dbo.Foo
SET y = 0
WHERE x = 1;
-- COMMIT TRANSACTION;
Trong một phiên riêng biệt, hãy chạy như sau:
SELECT *
FROM dbo.Foo WITH ( NOLOCK );
GO
SELECT *
FROM dbo.Foo;
Bạn có thể kiểm tra các khóa hiện đang được giữ bằng cách chạy sp_lock
, tốt nhất là trong một phiên riêng biệt khác:
EXECUTE dbo.sp_lock;
Bạn sẽ thấy một KEY
loại khóa được giữ bởi spid thực hiện giao dịch chèn trongX
chế độ (độc quyền), không bị nhầm lẫn với các khóa IX
(Intent-Exclusive) khác. Các khóa chứng chỉ ra rằng trong khi KEY
khóa là phạm vi cụ thể, nó cũng ngăn chặn các giao dịch khác từ chèn hoặc cập nhật các cột bị ảnh hưởng bởi thay đổi các dữ liệu chứa trong đó để nó có thể nằm trong phạm vi của truy vấn ban đầu. Vì bản thân khóa được giữ là độc quyền, truy vấn đầu tiên là ngăn truy cập vào tài nguyên từ bất kỳ giao dịch đồng thời nào khác. Trong thực tế, tất cả các hàng của cột bị khóa, cho dù chúng có nằm trong phạm vi được chỉ định bởi truy vấn đầu tiên hay không.
Các S
khóa được giữ bởi phiên thứ hai sẽ WAIT
cho đến khi X
khóa bị xóa, ngăn không cho khóa X
(hoặc U
) khác được lấy trên tài nguyên đó từ một spid đồng thời khác trước khi phiên thứ hai hoàn thành thao tác đọc của nó, chứng minh sự tồn tại của S
khóa.
Bây giờ là một chỉnh sửa cho rõ ràng: Trừ khi tôi nhầm lẫn về việc đọc bẩn là gì từ mô tả ngắn gọn về rủi ro được đề cập ở đây ... Chỉnh sửa 3 : Tôi chỉ nhận ra rằng tôi không xem xét ảnh hưởng của một điểm kiểm tra nền viết về giao dịch chưa được cam kết vào đĩa, vì vậy, giải thích của tôi là sai lệch.
Trong truy vấn thứ hai, lô đầu tiên có thể (và trong trường hợp này,) sẽ trả về dữ liệu không được cam kết. Lô thứ hai, chạy ở mức cô lập giao dịch mặc định READ COMMITED
sẽ chỉ trở lại sau khi hoàn thành cam kết hoặc khôi phục trong phiên đầu tiên.
Từ đây, bạn có thể xem các gói truy vấn của mình và các mức khóa liên quan, nhưng tốt hơn nữa, bạn có thể đọc tất cả về các khóa trong SQL Server tại đây .
SELECT * FROM Table1
nếu đó là chính xác những gì tôi cần?