在SQL中使用nolock的语法

13 浏览
0 Comments

在SQL中使用nolock的语法

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

select * from table1 nolock where column1 > 10

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

上述语句中哪个是正确的,为什么?

0
0 Comments

在SQL 2005之前,使用nolock关键字是合法的,但是自SQL 2005开始,官方已经弃用了不使用WITH关键字的写法。因此,现在使用WITH关键字是最佳实践。

在SQL 2005之后,使用with(nolock)成为了新的语法规范,尽管仍然可以只使用nolock关键字。但是需要注意的是,不使用WITH关键字的写法已经被弃用,这意味着在未来的某个版本中(可能是下一个版本,也可能是之后的版本,甚至可能是10个版本之后),该写法可能不再起作用。

关于INSERT和UPDATE语句,是否应该在其中使用with(nolock)作为编程规范?我认为在任何情况下都不应该将表提示视为编程规范 - 尽管有一些情况下可以/应该使用它们,但绝对不是“规范”。如果你问的是在INSERT和UPDATE语句中是否可以使用它们,你当然可以在INSERT和UPDATE的FROM子句中使用它们,但是你不能对写操作(即实际的INSERT和UPDATE)使用nolock。

对于INSERT、UPDATE和DELETE操作,nolock将被忽略 - 至少在SQL Server中是如此。写入部分将被忽略,这就是为什么不能对写操作使用nolock,但是可以在FROM子句中使用它们(例如:insert tableA (a,b,c) select d,e,f from tableB with(nolock)),tableB的查询将使用nolock,而tableA的部分将不使用nolock。

当我说“写入部分将被忽略”时,我是同意你的说法,即实际的INSERT、UPDATE和DELETE将忽略nolock关键字...阅读后有些令人困惑。

我明白了 - 这有点微妙。然而,我认为将数据修改和nolock这样混合使用是一个非常糟糕的做法。

对于大多数情况,我完全同意。

0
0 Comments

在SQL中,使用NOLOCK或READUNCOMMITTED来指定表提示在UPDATE或DELETE语句的FROM子句中已经被弃用。此外,不使用WITH关键字来指定表提示、在HOLDLOCK表提示中不使用括号、在表提示之间使用空格作为分隔符以及通过视图对多语句表值函数(TVF)的调用间接应用表提示等功能也已经被列入即将在下一个SQL版本之后删除的功能列表中。

这些功能将在下一个版本的SQL中被移除,意味着它们可能仅在较低的数据库兼容性级别下支持。

关于这个问题,我的建议如下:

- 无论是"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

然后从所有的查询中移除所有的提示。

虽然我同意脏读是有其用途的,但是我认为它被过度使用、误解,并且只有极少数情况下它是有意义的,甚至更少的情况下实际使用是被理解的。

NOLOCK已经在多个版本的SQL Server中被列为"下一个版本不支持的功能",包括2008、2014和2016年。

0
0 Comments

在SQL中使用nolock的语法是用于在查询时不加锁的。然而,有时候在使用nolock时会出现一些问题。在SQL Server 2005中测试时发现,如果在查询中使用select * from table1 nolock where column1 > 10,"nolock"会成为该查询中的别名,而不是起到不加锁的作用。要实现不加锁的功能,应该使用select * from table1 with(nolock) where column1 > 10。这样查询将会正确地不加锁。如果想要验证一下,可以在另一个窗口运行以下代码来锁定表:

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

然后分别在两个窗口中运行每个锁定语句。第一个语句将会一直等待锁被释放,而第二个语句将会立即执行(并且显示“脏数据”)。在完成测试后,不要忘记执行ROLLBACK来回滚事务。

在这个问题中,有人注意到了"(nolock) vs. nolock"的区别,以及别名的问题。应该强调的是使用"(nolock) vs. with(nolock)",而不是"nolock vs. with(nolock)",这是问题中所展示的。

0