我们存储过程中的大多数 select 语句都使用了WITH(NOLOCK)
,我的同事告诉我他们使用它来提高性能。现在,我知道这个提示有助于锁定,但它真的提高了性能吗?我在某处读到我们不应该NOLOCK
在 OLTP 数据库中使用提示,但我看到在我的工作场所正在做相反的事情。在使用提示时,有人可以阐明最佳做法吗NOLOCK
?
我们存储过程中的大多数 select 语句都使用了WITH(NOLOCK)
,我的同事告诉我他们使用它来提高性能。现在,我知道这个提示有助于锁定,但它真的提高了性能吗?我在某处读到我们不应该NOLOCK
在 OLTP 数据库中使用提示,但我看到在我的工作场所正在做相反的事情。在使用提示时,有人可以阐明最佳做法吗NOLOCK
?
未承诺
NOLOCK 提示是 READ UNCOMMITTED 隔离级别的同义词。在本回答期间,请将它们视为等同且可互换的。Read Uncommitted 在 SQL Server 中实现,以采用最少的架构锁来防止对正在查询的表进行更改。
使用任何一个仍将采用模式锁,但它们将被允许忽略尚未完成其任务并回滚或提交事务的修改查询(插入、更新、删除、合并)所采用的锁.
在事务内部使用独占锁定提示(例如 UPDLOCK)的那些读取查询之外的所有读取查询将按照存储引擎选择的不同粒度(行、页等)获取并快速释放锁定。读取查询没有锁升级。
区别在于隔离级别在遇到锁定的行、页面或对象时的行为方式。
在 Read Committed、Repeatable Read 和 Serializable 下,读查询被阻塞,直到修改释放它们的锁。
在 Read Committed Snapshot Isolation 和 Snapshot Isolation 下,读取查询将从版本存储中读取锁定行的最后一个已知良好版本。
许多“我的查询使用 NOLOCK 变得更快”的结论(错误地)来自于避免被阻止。在 Read Committed 下,读取查询在某些情况下也可能与修改查询发生阻塞和死锁。看:
使用 NOLOCK 作为查询提示或使用 Read Uncommitted 作为隔离级别将避免这些情况。同样,它们是同一回事。
当然还有一个额外的考虑,因为指定某些锁定提示的查询可以使用 IAM 扫描来读取更少的页面。
请注意,使用 NOLOCK 的查询和使用 TABLOCK 作为提示的查询在聚集索引扫描时存在约 6 秒的差异。
用法
既然你问:
从读未提交隔离级别:
为避免最烦人的阻塞和死锁情况,并返回正确的数据,读取提交快照隔离级别或快照隔离级别是您的最佳选择。