我可以强制用户使用 WITH NOLOCK 吗?

Pau*_*aul 6 sql-server sql-server-2008-r2

我可以强制用户的查询始终使用提示 NOLOCK 运行吗?例如他们输入

select * from customer
Run Code Online (Sandbox Code Playgroud)

但是在服务器上执行的是

select * from customer with (nolock)
Run Code Online (Sandbox Code Playgroud)

这个问题不是:
关于NOLOCK的各种优缺点,敬上。我知道它们是什么,这里不是讨论它们的地方。

Aar*_*and 18

真正的答案是:

停止使用 NOLOCK

其他可能有用的信息:

当然,拒绝对表/视图的直接访问,并通过存储过程(或视图 - 感谢 Martin)强制执行数据访问 - 您可以编码使用NOLOCK

如果您需要按用户进行访问,并且可以通过过程强制执行数据访问,则可以使用SQLMenace 此处建议的想法

CREATE PROCEDURE dbo.blah
AS
BEGIN
  SET NOCOUNT ON;

  IF SUSER_SNAME() = N'something'
  BEGIN
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
  END

  SELECT columns FROM dbo.Customer;
END
GO
Run Code Online (Sandbox Code Playgroud)

或者你也可以这样做:

CREATE PROCEDURE dbo.blah
AS
BEGIN
  SET NOCOUNT ON;

  IF SUSER_SNAME() = N'something'
  BEGIN
    SELECT columns FROM dbo.Customer WITH (NOLOCK);

    RETURN;
  END

  SELECT columns FROM dbo.Customer;
END
GO
Run Code Online (Sandbox Code Playgroud)

如果这是不可能的,我想建议一个计划指南,但我还没有用它们来强制执行NOLOCK。此外本文档中的联机丛书表明,这是留给INDEXFORCESCANFORCESEEK提示。NOLOCK如果查询文本中尚不存在,则使用计划指南尝试添加会导致错误。但是,示例 K 中显示的代码似乎与此相矛盾,因此也许值得一试。当然,您需要为每个查询设置一个计划指南,这可能会令人望而却步(或不可能),而且它们并不完全适合内心虚弱的人。

而且我知道您不想听到 的缺点NOLOCK,但是强制每个人都使用快照会更容易(而且更好!)。

为了解决 Kenneth 关于使用登录触发器的建议:在我的测试中,可以在登录触发器中指定此 SET 选项,但就像在存储过程中设置它一样,当触发器超出范围时,设置将恢复为服务器默认值。所以不,似乎没有办法从登录触发器设置会话的隔离级别。


db2*_*db2 7

正如其他人所说:不要随意使用 NOLOCK。在某些时候它是合适的,并且“来自特定用户的每个查询”可能不是其中之一。使用更好、更安全的选项之一来处理并发性,或者如果您的 DBA/开发人员经常用糟糕的查询来干扰生产系统,则使用您最喜欢的 LART。

是的,您可以调整安全性,以便他们只能从从带有 NOLOCK 提示的基表中选择的视图中进行选择,我可以想象可能需要的几种情况(运营支持人员需要偶尔实时检查生产数据,也许还省略了一些敏感信息/列)。

但是考虑一下这个类似的讨论:

“我怎样才能把我的车开到三楼?”

“你为什么想这么做?”

如果答案是“因为我的公司在三楼,我需要展示汽车以进行促销/赠品”,那么您就开始寻找将它放在那里的方法。

但如果答案是“因为我想回到我的三楼公寓”,那么正确的建议是“所以把你的车停在停车场,下车,乘电梯到三楼。”

不要将假设和偏见转化为技术要求,也不要拘泥于您对解决方案的第一次尝试。退后一步,重新评估您想要完成的工作。


Fab*_*ujo 5

似乎您可以在不使用 SP 的情况下获得最近的使用SET READ_COMMITTED_SNAPSHOT,这将影响数据库的所有用户。

READ_COMMITTED_SNAPSHOT数据库选项可以控制,如果隔离级别READ_COMMITTED是像他们在PostgreSQL和FirebirdSQL(记录语句级快照)对口实现或使用锁定。在文档中阅读更多相关信息:

锁定和行版本控制

您在回复另一个答案时发表了评论:

心目中的场景中没有控制应用程序。它是针对 SQL2008R2 标准版的直接 SSMS

您必须确保在工具/选项/查询执行/SQL Server/高级中将所有安装设置为读取未提交。我自己不是网络系统管理员,所以我不知道策略是否可以解决它。