EXISTS 查询仍会锁定表吗?
IF NOT EXISTS(SELECT * FROM MyTable WITH(nolock) WHERE Key = 'MyKey')
INSERT MyTable(Key) Values('MyKey')
如果表中不存在该值,查询是否需要锁?
IF NOT EXISTS(SELECT * FROM MyTable WITH(nolock) WHERE Key = 'MyKey')
INSERT MyTable(Key) Values('MyKey')
If The value does not exist in the table, does the query aquire a lock?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
来自文档:
因此它不会获取数据锁,但仍会获取架构稳定性锁。
From the docs:
So it won't acquire a data lock, but it will still acquire a schema stability lock.
EXISTS 通常仍会获取锁。但你添加了一个提示,告诉它不要这样做,所以它不会。
EXISTS normally will still acquire a lock. But you added a hint that told it not to, and so it won't.
使用 NOLOCK 提示确实可以防止行锁。但请注意,这种“查找和插入”充满了问题。该操作不是原子操作,当两个会话都发现密钥丢失并都尝试插入时,尝试执行此操作的两个会话将导致竞争条件,从而导致其中一个会话导致重复密钥冲突。它是否也是次优的,因为索引查找发生两次(一次查找键,一次定位插入位置)。最佳且正确的解决方案是实际尝试插入重复键错误并从该错误中恢复(如果已存在)。
Using a NOLOCK hint will indeed prevent the row lock. Just a heads up though, this kind of 'lookup and insert' is riddled with problems. The operation is not atomic and two sessions trying to do it will cause a race condition when both find the key missing and both try to insert, resulting in one of them causing a duplicate key violation. Is it also suboptimal because the index seek occurs twice (once to lookup the key, once to locate the insert position). The optimal and correct solution is to actually try to insert and recover from the duplicate key error if already exists.
该代码很容易出错。相反,您可以尝试:
在表上放置一个唯一索引,以便不可能插入多个冲突的行,然后直接插入。冲突会产生错误,您需要处理该错误。
或者,如果冲突是预期条件而不是异常,那么您需要使插入/检查原子化:
另外,请注意,(nolock) 和 Read Uncommissed 根据设计不会产生准确的结果。对于报告等来说是可以的,但是根据使用(nolock)的决策对数据采取行动是危险的。
That code is vulnerable to error. Instead you could try:
Put a unique index on the table so that it's not possible to insert multiple rows that conflict, and then just insert. A conflict generates an error, which you'd need to handle.
Or, if conflicts are an expected condition and not the exception, then you'll want to make the insert/check atomic:
Also, note that (nolock) and Read Uncommitted do not produce accurate results, by design. It's OK for reporting and such, but dangerous to act on your data based on a decision that uses (nolock).