【问题标题】:syntax for nolock in sqlsql中nolock的语法
【发布时间】:2009-11-12 17:21:55
【问题描述】:

我见过使用 nolock 和 with(nolock) 的 sql 语句 例如 -

select * from table1 nolock where column1 > 10

与

select * from table1 with(nolock) where column1 > 10

以上哪些说法是正确的,为什么?

【问题讨论】:

    标签: sql-server syntax nolock


    【解决方案1】:

    第一条语句不锁定任何东西,而第二条语句则锁定。当我刚刚在 SQL Server 2005 上进行测试时,在

    select * from table1 nolock where column1 > 10 --INCORRECT
    

    “nolock”成为该查询中 table1 的别名。

    select * from table1 with(nolock) where column1 > 10
    

    执行所需的 nolock 功能。持怀疑态度?在单独的窗口中,运行

    BEGIN TRANSACTION
    UPDATE tabl1
     set SomeColumn = 'x' + SomeColumn
    

    锁定表,然后在其自己的窗口中尝试每个锁定语句。第一个将挂起,等待锁被释放,第二个将立即运行(并显示“脏数据”)。不要忘记发布

    ROLLBACK
    

    当你完成时。

    【讨论】:

    • +1 用于区分 (nolock) 与 nolock - 关于别名的内容。区别应该是使用“(nolock)vs. with(nolock)”而不是“nolock vs. with(nolock)”,如问题所示 - good catch
    【解决方案2】:

    弃用功能列表位于Deprecated Database Engine Features in SQL Server 2008:

    • 指定 NOLOCK 或 READUNCOMMITTED 在 UPDATE 的 FROM 子句中或 删除语句。
    • 指定表 不使用 WITH 关键字的提示。
    • HOLDLOCK 表提示没有 括号
    • 使用空格作为表格提示之间的分隔符。
    • 通过视图将表提示间接应用于多语句表值函数 (TVF) 的调用。

    它们都在下一个 SQL 版本后有时会被删除的功能列表中,这意味着它们可能会在下一个版本中仅在较低的数据库兼容性级别下得到支持。

    据说我在这个问题上的 2c 是这样的:

    • from table nolock 和 from table with(nolock) 都是错误的。如果你需要脏读,你应该使用适当的transaction isolation 级别:set transaction isolation level read uncommitted。这样,所使用的隔离级别就可以通过一个“旋钮”明确说明和控制,而不是通过源分散开来并受制于表格提示的所有怪癖(通过视图和 TVF 等间接应用)。
    • 脏读是一种厌恶。在 99.99% 的情况下,需要的是减少争用,而不是读取未提交的数据。通过针对设计良好的模式编写适当的查询以及在必要时部署快照隔离来减少争用。解决工作的最佳解决方案几乎总是保存一些极端情况,是在数据库中 enable read commited snapshot 并让引擎发挥它的魔力:

      ALTER DATABASE MyDatabase SET ALLOW_SNAPSHOT_ISOLATION ON
      ALTER DATABASE MyDatabase SET READ_COMMITTED_SNAPSHOT ON

    然后从选择中删除所有提示。

    【讨论】:

    • +1 有几件事,我第一次注意到 FROM 中的 nolock 弃用更新/删除 - 非常好。虽然我不完全同意脏读是可憎的(在某些情况下使用它实际上是有意义的,即使在读取提交的乐观方法中也是如此),我同意它被过度使用、被误解,并且有非常, 真正有意义的场景很少,真正理解使用的场景更少。
    • 我同意脏读有其用处,但可以说我喜欢使用戏剧效果来强调信息。
    • NOLOCK 已被列为多个 SQL Server 版本的“SQL Server 下一版本不支持的功能”。 2008 年、2014 年和 2016 年。
    【解决方案3】:

    它们在技术上都是正确的,但是 not using the WITH keyword has been deprecated 从 SQL 2005 开始,所以习惯使用 WITH 关键字 - 简短的回答,使用 WITH 关键字。

    【讨论】:

    • 好的,所以 with(nolock) 几乎已经成为 sql 2005 的新语法,尽管 nolock 本身仍然有效。是吗?
    • 是的,在没有“with”的情况下仍然可以工作,但它已被弃用,这意味着它很可能在未来某个时间点的发布中不会以这种方式工作(可能是下一个版本,可能成为之后的那个,从现在开始可能是 10 个)...
    • 还有关于插入,更新应该与(nolock)一起用作编程规范吗?
    • 我不会说以任何方式使用表提示将/应该被视为编程规范 - 在某些情况下可以/应该使用它,但绝对不是“规范”。如果你问能否在插入/更新语句中使用它们,你当然可以在插入/更新的 FROM 子句中使用它们,但你不能锁定写入(即实际的插入/更新)。
    • 写入部分将,是的 - 因此您不能锁定写入但您可以在子句的 FROM 部分中使用它们的语句(即 insert tableA (a,b,c) select d,e,f from tableB with(nolock)) - tableB 查找/扫描将遵守 nolock,tableA 部分不会。
    【解决方案4】:

    使用“WITH (NOLOCK)”。

    【讨论】:

      【解决方案5】:

      两者在语法上都是正确的。

      NOLOCK 将成为 table1 的别名。

      WITH (NOLOCK) 通常被用作加快数据库读取速度的神奇方式,但我尽量避免使用它。

      结果集可以包含尚未提交的行,这些行通常稍后会回滚。

      错误或结果集可以为空、缺少行或多次显示同一行。

      这是因为在您读取数据的同时其他事务正在移动数据。

      READ COMMITTED 增加了一个额外的问题,即多个用户同时更改同一单元格的单个列中的数据损坏。

      还有其他副作用,这会导致牺牲您最初希望获得的速度提升。

      现在你知道了,再也不要使用它了。

      【讨论】:

        猜你喜欢
        • 2016-11-21
        • 2017-10-23
        • 2017-11-19
        • 2020-10-01
        • 2011-04-22
        • 1970-01-01
        • 1970-01-01
        • 2020-04-28
        • 1970-01-01
        相关资源
        最近更新 更多