我有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时,锁仍然会被应用,并且这些地方可能会导致死锁。