SQL Server,误导性的 XLOCK &优化
从我最近所做的一些测试和阅读来看,XLOCK 的“X”(独占)名称部分似乎具有误导性。事实上,它并不比 UPDLOCK 多加锁。如果它是独占的,它将阻止外部 SELECT,但事实并非如此。
我无法从阅读或测试中看出两者之间的区别。
XLOCK 唯一一次创建独占锁是与 TABLOCK 一起使用时。 我的第一个问题是“为什么只在这个粒度?”
此外,我遇到了博客 声明以下内容:
但是,请注意 XLOCK 提示。 SQL Server 将有效地忽略 XLOCK 提示!有一个优化,SQL Server 检查自最旧的打开事务以来数据是否已更改。如果不是,则忽略 xlock。这使得 xlock 提示基本上毫无用处,应该避免。
有人遇到过这种现象吗?
根据我所看到的,似乎应该忽略这个提示。
From some recent testing and reading I've done, it seems the "X" (exclusive) name part of XLOCK is misleading. It in fact doesn't lock any more than UPDLOCK. If it were exclusive, it would prevent external SELECTs, which it doesn't.
I cannot see either from reading or from testing and difference between the two.
The only time XLOCK creates an exclusive lock is when used with TABLOCK. My first question is "why only at this granularity?"
Further, I came across a blog that states the following:
However, watch out for XLOCK hint. SQL Server will effectively ignore XLOCK hint! There's an optimization where SQL Server check whether the data has changed since the oldest open transaction. If not, then an xlock is ignored. This makes xlock hints basically useless and should be avoided.
Has anyone run across this phenomenon?
Based on what I'm seeing, it seems this hint should be ignored.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
X
锁与U
锁的排他性在 可以看出,
X
锁仅兼容schema稳定性和Insert Range-Null锁类型。U
与以下附加共享锁类型兼容S
/IS
/RS-S
/RI -S
/RX-S
锁兼容性矩阵 http://i.msdn.microsoft.com/ms186396.LockConflictTable(en-us,SQL.105).gif
X
锁的粒度这些各级都被罚款。下面的脚本和探查器跟踪演示了它们已在行级别成功取出。
但行仍然可以读取!
事实证明,在
已提交读
隔离级别,SQL Server 并不总是会取出S
锁,如果不存在读取未提交数据的风险,它将跳过此步骤。这意味着不能保证永远发生锁冲突。但是,如果初始选择是
with (paglock,XLOCK)
,则此将停止读取事务,因为页面上的X
锁将阻止读取事务。IS
读者始终需要的页面锁定。这当然会对并发产生影响。其他注意事项
即使您锁定行/页,这并不意味着您阻止对表中该行的所有访问。聚集索引中的行上的锁不会阻止查询从覆盖非聚集索引中的相应行读取数据。
Exclusivity of
X
locks vsU
locksIn the lock compatibility matrix below it can be seen that the
X
lock is only compatible with the schema stability and Insert Range-Null lock types.U
is compatible with the following additional shared lock typesS
/IS
/RS-S
/RI-S
/RX-S
lock compatibility matrix http://i.msdn.microsoft.com/ms186396.LockConflictTable(en-us,SQL.105).gif
Granularity of
X
locksThese are taken out fine at all levels. The script and profiler trace below demonstrates them being successfully taken out at row level.
But rows can still be read!
It turns out that at
read committed
isolation level SQL Server will not always take outS
locks, it will skip this step if there is no risk of reading uncommitted data without them. This means that there is no guarantee of a lock conflict ever occurring.However if the initial select is
with (paglock,XLOCK)
then this will stop the reading transaction as theX
lock on the page will block theIS
page lock that will always be needed by the reader. This will of course have an impact on concurrency.Other Caveats
Even if you lock the row/page this does not mean that you block all accesses to that row in the table. A lock on a row in the clustered index will not prevent queries reading data from the corresponding row in a covering non clustered index.
这不是一个警告,而是对 SELECT 中发生的情况的误解。
如果页面不包含脏数据,则单纯的 SELECT 不会请求共享锁,因此不会被 XLOCK 阻塞。
要被 XLOCK 阻止,需要在 REPEATABLE READ 隔离级别下运行。有两件事可以触发:
It's not a caveat, it's a misunderstanding on what happens in SELECT.
A mere SELECT does not asks for Shared locks if the pages do not contain dirty data, and thus is not blocked by XLOCK.
To be blocked by XLOCK, you need to run in REPEATABLE READ isolation level. Two things can trigger that:
根据@Martin的回答中的评论,这是小脚本(在不同的 SSMS 窗口中运行不同的部分来测试阻止 SELECT 的锁定:
based on the comments in @Martin's answer, here is a little script (run the different parts in different SSMS windows to test the lock preventing a SELECT: