WITH(NOLOCK):其中&何时使用

时间:2015-12-23 10:29:49

标签: sql sql-server tsql

我有15个表被规范化以包含记录,并且许多用户可能正在这些表中插入/更新数据(没有两个用户可以同时更新相同的记录,这受到客户端实现的限制)。这15个表在存储过程中逐个更新。 WITH(NOLOCK)用于select语句以避免读锁定,因为某些用户可能同时查看数据。但有时在这些过程中会锁定这些select语句。根据我过去的经验,我把这些nolock用来避免阻塞。

我不确定是否在某处丢失了WITH(NOLOCK)或这是其他问题。 Should I search for missing WITH(NOLOCK)?

or what other ways are there to avoid this locking?

  

NOLOCK有哪些限制?我只是在阅读数据,我不在乎我是否读取了已提交或未提交的数据。还有什么   可以采取措施删除此阻止?

4 个答案:

答案 0 :(得分:7)

WITH(NOLOCK):

WITH(NOLOCK)相当于使用READ UNCOMMITED作为事务隔离级别。

基本上它给了脏读。即如果任何事务持有一些数据,然后我们尝试获取数据,它将提供输出而无需等待事务提交。这样我们就可以在没有等待的情况下获得脏读。

因此,您将面临读取随后回滚的未提交行的风险,即从未进入数据库的数据。因此,虽然它可以防止读取被其他操作陷入僵局,但它带来了风险。在具有高交易率的银行应用程序中,对于您尝试用它解决的任何问题,它可能不会是正确的解决方案。

https://social.msdn.microsoft.com/Forums/sqlserver/en-US/a3b1d05b-5479-485b-94c5-4f271adf5802/where-to-and-where-not-to-use-with-nolock?forum=transactsql

答案 1 :(得分:2)

当您使用未提交的数据时,请使用WITH(NOLOCK)。

它会为您带来严重的性能提升,因为您的查询不会等待任何未提交的事务完成。它是一个很棒的工具,但必须小心使用,否则你将无法承受无法承受的数据。

答案 2 :(得分:2)

我认为根据您在原始帖子上留下的评论,您想要做的是将隔离级别设置为READ UNCOMMITED。这与NO LOCK相同,只是它将其设置在整个事务上而不是单独的select语句上。

代码示例:

USE DatabaseName;
GO
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITED;
GO
BEGIN TRANSACTION;
GO
...
COMMIT TRANSACTION;
GO

这应该可以防止对数据库的任何锁定以进行读取。然而,这也将适用于插入,这可能会出现我想象的可能的并发问题。插入时数据可能会发生变化。

如果您计划在此隔离级别下对数据库进行更新,我会重新考虑此问题。

以下是ms sql隔离级别的更多详细信息:https://msdn.microsoft.com/en-za/library/ms173763.aspx

答案 3 :(得分:0)

WITH(NOLOCK)通常被用作提高数据库读取速度的一种神奇方法。

仅在具有聚集索引的表的SELECT语句中使用WITH (NOLOCK)

提示:确保表具有聚集索引的最简单方法是添加一个自动递增的ID主键列。

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

如果将WITH(NOLOCK)应用于具有非聚集索引的表,则在将行数据流式传输到结果表时,其他事务可以更改行索引。这意味着结果集可以缺少行多次包含同一行

READ COMMITTED(读取已提交)又增加了一个问题,即数据在单个列中损坏,多个用户同时更改同一单元格。

使用INSERT,UPDATE或DELETE时,锁仍将应用,并且这些位置可能会导致死锁。