Kin*_*han 4 sql-server select nolock
我正在阅读这里的答案(来自stackoverflow,我认为应该在这里提问)
NOLOCK 意味着根本不放置锁。
您的查询可能会在单个查询中返回 UPDATE 之前的部分数据和 UPDATE 之后的部分数据。
我知道 nolock 不会锁定表,所以其他人可以同时查询。
从它显示的答案和示例来看,它在数据更新时获取数据。
为什么会这样?
我假设对于普通选择,它会尝试在表上加锁,因此当执行更新语句时,它会在行或页上加锁。然后当我尝试运行 select 语句时,它无法放置锁,直到更新语句锁被释放。
但是在这种情况下因为select语句不会尝试给表加锁,所以它可以运行而无需等待update语句释放锁?
Mar*_*ith 10
这并不完全正确,这NOLOCK
意味着根本不放置锁。在这个提示下的查询仍然需要Sch-S
锁和(可能是 HOBT
锁)。
在read committed
隔离级别下,SQL Server 将(通常)获取行级S
锁并在读取数据后立即释放它们。这些与X
未提交更新上的锁不兼容,因此可以防止脏读。
在链接答案的示例中,SELECT
查询在遇到修改后的行时不会被阻止,因此很可能读取部分更新。
它也可能发生在默认read committed
隔离级别,尽管 aSELECT
读取一些具有“before”值的行而另一些具有“after”值的行。只需要设计一种情况
R1
并释放其S
锁R2
并获取X
锁R2
并被阻止。R1
并获取X
锁。R2
例如,如果SELECT
和UPDATE
使用不同的索引来定位感兴趣的行,则可能会出现这种类型的情况。
例子
CREATE TABLE T
(
X INT IDENTITY PRIMARY KEY,
Y AS -X UNIQUE,
Name varchar(10),
Filler char(4000) DEFAULT 'X'
)
INSERT INTO T (Name)
SELECT TOP 2500 'A'
FROM master..spt_values
Run Code Online (Sandbox Code Playgroud)
现在在一个查询窗口中运行
DECLARE @Sum int
SELECT 'SET @@ROWCOUNT' WHERE 1=0
WHILE (@@ROWCOUNT = 0)
SELECT @Sum = SUM(LEN(Name))
FROM T
WHERE Y IN (-1, -2500)
HAVING SUM(LEN(Name)) = 3
Run Code Online (Sandbox Code Playgroud)
这将无限循环运行。在另一个运行中
UPDATE T
SET Name=CASE WHEN Name = 'A' THEN 'AA' ELSE 'A' END
Run Code Online (Sandbox Code Playgroud)
这可能会停止另一个查询中的循环(如果没有,请重试),这意味着它必须已读取A,AA
或AA,A
归档时间: |
|
查看次数: |
6699 次 |
最近记录: |