WITH(NOLOCK):何时何地使用



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

我不确定是WITH(NOLOCK)在某个地方丢失,还是其他问题Should I search for missing WITH(NOLOCK)?

or what other ways are there to avoid this locking?

NOLOCK有哪些限制?我只是在读数据,我不在乎我读的是提交的还是未提交的数据。还有什么可以采取措施来消除这种阻碍吗

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

如果可以使用未提交的数据,请使用WITH(NOLOCK)。

它会给您带来严重的性能提升,因为您的查询不会等待任何未提交的事务完成。这是一个很好的工具,但必须小心使用,否则在您负担不起的情况下,您最终会收到未提交的数据。

我认为,根据您在原始帖子上留下的评论,您想做的是将隔离级别设置为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

WITH(NOLOCK)经常被用作加速数据库读取的神奇方法。

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

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

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

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

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

当使用INSERT、UPDATE或DELETE时,锁仍然会被应用,并且这些地方可能会导致死锁。

最新更新