【发布时间】: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
我见过使用 nolock 和 with(nolock) 的 sql 语句 例如 -
select * from table1 nolock where column1 > 10
与
select * from table1 with(nolock) where column1 > 10
以上哪些说法是正确的,为什么?
【问题讨论】:
标签: sql-server syntax nolock
第一条语句不锁定任何东西,而第二条语句则锁定。当我刚刚在 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
当你完成时。
【讨论】:
弃用功能列表位于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 ONALTER DATABASE MyDatabase SET READ_COMMITTED_SNAPSHOT ON
然后从选择中删除所有提示。
【讨论】:
它们在技术上都是正确的,但是 not using the WITH keyword has been deprecated 从 SQL 2005 开始,所以习惯使用 WITH 关键字 - 简短的回答,使用 WITH 关键字。
【讨论】:
使用“WITH (NOLOCK)”。
【讨论】:
两者在语法上都是正确的。
NOLOCK 将成为 table1 的别名。
WITH (NOLOCK) 通常被用作加快数据库读取速度的神奇方式,但我尽量避免使用它。
结果集可以包含尚未提交的行,这些行通常稍后会回滚。
错误或结果集可以为空、缺少行或多次显示同一行。
这是因为在您读取数据的同时其他事务正在移动数据。
READ COMMITTED 增加了一个额外的问题,即多个用户同时更改同一单元格的单个列中的数据损坏。
还有其他副作用,这会导致牺牲您最初希望获得的速度提升。
现在你知道了,再也不要使用它了。
【讨论】: