Dat*_*irl 34 sql-server locking nolock
我是一名报表开发人员,希望尽可能提高我的查询效率。我曾经与一位 DBA 一起工作,他告诉我 - 我相信是因为我总是在生产服务器上处理报告 -NOLOCK在每个查询中使用。
现在,我与一个NOLOCK在任何情况下都被禁止的 DBA 一起工作- 即使我的报告(由于几个表上缺乏索引)正在停止复制和系统更新。在我看来,在这种情况下,aNOLOCK将是一件好事。
由于我的大部分 SQL 培训都是来自不同意见的 DBA,因此我想向各种各样的 DBA 提出这个问题。
Mar*_*ith 33
它并不总是坏的。
当然,它允许您读取未提交的值(可能会回滚,因此从逻辑上不存在)以及允许多次读取值或根本不读取值等现象。
保证您不会遇到任何此类异常的唯一隔离级别是可序列化/快照。如果在扫描到达该行之前移动了一行(由于键更新),则可重复读取值可能会丢失,如果键更新导致先前读取的行向前移动,则读取提交值可以读取两次。
nolock然而,这些问题更有可能出现,因为默认情况下,在此隔离级别,当它估计有超过 64 个要读取的页面时,它将使用分配顺序扫描。除了由于索引键更新而在页面之间移动行时出现的问题类别,这些分配顺序扫描也容易受到页面拆分问题的影响(如果新分配的页面在文件中早于点如果已扫描的页面被拆分到文件中的后续页面,则已扫描或阅读两次)。
至少对于简单(单表)查询,可以阻止使用这些扫描并nolock通过简单地向ORDER BY index_key查询添加 a来获得键有序扫描 at ,以便 the 的Ordered属性IndexScan是true。
但是,如果您的报告应用程序不需要绝对精确的数字并且可以容忍这种不一致的可能性更大,那么它可能是可以接受的。
但是当然您不应该在所有查询中都放弃它,希望它是一个神奇的“涡轮”按钮。除了在该隔离级别遇到异常结果或根本没有结果(“由于数据移动而无法使用 NOLOCK 继续扫描”错误)的更大概率之外,甚至在某些情况下,性能nolock 可能会更差。
Rem*_*anu 31
如果您的报告阻止了 DBA 正确的更新:您绝对不应该使用NOLOCK. 张女士说,有有冲突清楚地表明,如果你会用脏读,你会得到不正确的报告。
在我看来,总有比NOLOCK以下更好的选择:
SET TRANSACTION ISOLATION LEVEL,而不是查询提示。以后修复隔离级别而不是修改每个查询会更容易。我创建的大多数报告都不是基于当前数据运行的。大多数客户的运行报告都是昨天的数据。如果是这样,你的答案会改变吗?
如果是这种情况,那么您还有另一种可能的选择:您可以从生产数据库的副本运行报告,
而不是在生产数据库上运行查询并使用锁和NOLOCK。
您可以将其设置为每晚从备份中自动恢复。
显然您的报告在客户站点的服务器上运行,所以我不知道设置它是否对您来说是一个可行的解决方案。
(但话又说回来......无论如何他们应该有备份,所以你需要的只是一些服务器空间来恢复它们)
我是一名内部开发人员,所以这对我来说更容易,因为我可以完全控制服务器和数据库。
您至少可以对只需要昨天和更早数据的报告执行此操作。也许一些报告将不得不保留在生产数据库上,但至少您将一些负载转移到另一个数据库(或者甚至更好,另一个服务器)。
我在工作中也有同样的情况:
我们使用这样的生产数据库副本来处理几乎所有的报告内容,但有一些查询需要今天的数据。
| 归档时间: |
|
| 查看次数: |
4430 次 |
| 最近记录: |