一位同事写了一个使用提示“with(NOLOCK,NOWAIT)”的查询。
e.g。
select first_name, last_name, age
from people with (nolock,nowait)
假设:
NOLOCK说“不要担心任何级别的锁定,只需现在读取数据”
NOWAIT说“不要等,如果桌子被锁定就会出错”
问题:
为什么同时使用两者?当然NOWAIT永远不会实现,因为NOLOCK意味着它不会等待锁定......?
答案 0 :(得分:5)
这是多余的(或至少是无效的)。在一个查询窗口中,执行:
create table T (ID int not null)
begin transaction
alter table T add ID2 int not null
打开此窗口,打开另一个查询窗口并执行:
select * from T WITH (NOLOCK,NOWAIT)
尽管有NOWAIT
提示,尽管它被记录为在遇到任何锁定时立即返回消息,但第二个查询将挂起,等待Schema锁定。
<击> 阅读Table Hints上的文档:
NOWAIT
:
指示数据库引擎在表上遇到锁定时立即返回消息
请注意,这是关于锁定,任何锁定。
NOLOCK
(嗯,实际上是READUNCOMMITTED
):
READUNCOMMITTED和NOLOCK提示仅适用于数据锁。所有查询(包括具有READUNCOMMITTED和NOLOCK提示的查询)在编译和执行期间都会获取Sch-S(模式稳定性)锁。因此,当并发事务在表上持有Sch-M(模式修改)锁时,将阻止查询。
因此,NOLOCK
确实需要等待某些锁定。
击>
答案 1 :(得分:3)
NOLOCK
与READUNCOMMITTED
相同,MSDN states:
...由其他交易设置的排他锁不阻止当前 读取锁定数据的交易。
根据该句子,我会说你是正确的,并且发布NOLOCK
实际上意味着任何数据锁都无关紧要,因此NOWAIT
是多余的,因为查询无法被阻止。
然而,文章接着说:
READUNCOMMITTED和NOLOCK提示仅适用于数据锁
您还可以获取架构修改锁,NOLOCK
不能忽略这些锁。如果您在更新架构对象时使用NOLOCK
发出了查询,则可能会被Sch-M类型的锁阻止您的查询。
有趣的是,在不太可能的情况下,NOWAIT
是否真正受到尊重。但是出于你的目的,我猜它可能是多余的。
答案 2 :(得分:1)
将它们一起使用没有任何意义。 NOLOCK会覆盖NOWAIT 的行为。这是NOWAIT功能的演示。评论NOLOCK并观看记录返回,尽管有独家锁定。
创建表格。执行第一个SSMS窗口而不提交事务。由于没有等待,执行第二个窗口会出错。注释掉第一个查询并使用NOLOCK和NOWAIT执行第二个查询。得到结果。完成后回滚您的交易。
<强> DDL 强>
USE [tempbackup]
GO
/****** Object: Table [TEST_TABLE] Script Date: 02/19/2014 09:14:00 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [TEST_TABLE](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NULL,
CONSTRAINT [PK_TEST_TABLE] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
INSERT INTO tempbackup.dbo.TEST_TABLE(Name) VALUES ('MATT')
GO
SSMS WINDOW 1
BEGIN TRANSACTION
UPDATE tempbackup.dbo.TEST_TABLE WITH(XLOCK) SET Name = 'RICHARD' WHERE ID = 1
--ROLLBACK TRANSACTION
SSMS WINDOW 2
SELECT * FROM tempbackup.dbo.TEST_TABLE WITH(NOWAIT)
--SELECT * FROM tempbackup.dbo.TEST_TABLE WITH(NOLOCK,NOWAIT)