我见过使用 nolock 和 with(nolock) 的 sql 语句,例如 -
select * from table1 nolock where column1 > 10
和
select * from table1 with(nolock) where column1 > 10
上述哪些陈述是正确的,为什么?
我见过使用 nolock 和 with(nolock) 的 sql 语句,例如 -
select * from table1 nolock where column1 > 10
和
select * from table1 with(nolock) where column1 > 10
上述哪些陈述是正确的,为什么?
第一条语句不锁定任何东西,而第二条语句则锁定。当我刚才在 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
当你完成时。
弃用功能列表位于 SQL Server 2008 中弃用的数据库引擎功能:
- 在 UPDATE 或 DELETE 语句的 FROM 子句中指定 NOLOCK 或 READUNCOMMITTED。
- 在不使用 WITH 关键字的情况下指定表提示。
- 不带括号的 HOLDLOCK 表提示
- 使用空格作为表格提示之间的分隔符。
- 表提示间接应用于通过视图调用多语句表值函数 (TVF)。
它们都在 SQL 的下一个版本之后有时会被删除的特性列表中,这意味着它们可能会在较低的数据库兼容性级别下在 enxt 版本中得到支持。
话虽如此,我在这个问题上的 2c 是这样的:
from table nolock
。from table with(nolock)
如果你需要脏读,你应该使用适当的事务隔离级别:set transaction isolation level read uncommitted
. 通过这种方式,使用的隔离级别明确说明并从一个“旋钮”控制,而不是通过源分散并受制于表格提示的所有怪癖(通过视图和 TVF 等间接应用)。脏读是一种厌恶。在 99.99% 的情况下,需要的是减少争用,而不是读取未提交的数据。通过针对设计良好的模式编写适当的查询以及在必要时部署快照隔离来减少争用。解决工作的最佳解决方案几乎总是保存一些极端情况,是在数据库中启用读取提交快照并让引擎发挥其魔力:
ALTER DATABASE MyDatabase SET ALLOW_SNAPSHOT_ISOLATION ON
ALTER DATABASE MyDatabase SET READ_COMMITTED_SNAPSHOT ON
然后从选择中删除所有提示。
它们在技术上都是正确的,但是从 SQL 2005开始不推荐使用 WITH 关键字,因此请习惯使用 WITH 关键字 - 简短的回答,请使用 WITH 关键字。
使用“WITH (NOLOCK)”。
两者在语法上都是正确的。
NOLOCK 将成为 table1 的别名。
WITH (NOLOCK) 通常被用作加快数据库读取速度的神奇方式,但我尽量避免使用它。
结果集可以包含尚未提交的行,这些行通常稍后会回滚。
错误或结果集可以为空、缺少行或多次显示同一行。
这是因为在您读取数据的同时其他事务正在移动数据。
READ COMMITTED 增加了一个额外的问题,即多个用户同时更改同一单元格的单个列中的数据损坏。
还有其他副作用,这会导致牺牲您最初希望获得的速度提升。
现在你知道了,永远不要再使用它了。