我是一名报告开发人员,希望使我的疑问效率尽可能高效。我曾经与告诉我的DBA合作 - 我相信,因为我一直在处理生产服务器上的报告 - NOLOCK 在每个查询中。

现在,我与已禁止的DBA合作 NOLOCK 在任何情况下 - 即使我的报告(由于几个表上的索引非常缺乏),也在停止复制和系统更新。在我看来,在这种情况下, NOLOCK 会是一件好事。

由于我的大多数SQL培训都以不同的意见出现了各种DBA,因此我想向各种DBA询问。

有帮助吗?

解决方案

如果您的报告阻止了您的DBA正确的更新:您绝对不应该使用 NOLOCK. 。那里的事实 冲突清楚地表明,如果您 使用肮脏的读取,您会收到不正确的报告。

我认为,总是有比 NOLOCK:

  • 您的生产表是否仅读取有效并且永远不会被修改?仅标记数据库读取!
  • 表扫描会导致锁冲突?适当地索引表,好处是多重的。
  • 不能修改/不知道如何适当索引?利用 快照隔离.
  • 无法更改应用程序使用快照?打开 读取合并的快照!
  • 您已经测量了行版本的影响,并有证据表明它会影响性能吗?您无法索引数据?而且你还可以 不正确的报告?然后,至少要帮自己一个忙并使用 SET TRANSACTION ISOLATION LEVEL, ,不是查询提示。以后修复隔离级别而不是修改每个查询将更容易。

其他提示

不是 总是 坏的。

当然,它允许您读取非承诺的值(可能会回滚,因此从逻辑上不存在),并且允许多次或根本不读取诸如读取值之类的现象。

保证您不会遇到任何此类异常的唯一隔离级别是可序列化/快照。如果在扫描到达该行之前移动一行(由于密钥更新),则可能会丢失在可重复的读取值下,如果键更新导致先前读取的行前进,则可以读取两次读取值。

这些问题更有可能在 nolock 但是,默认情况下,在此隔离级别将使用 分配有序扫描估计有超过64页要读取. 。以及由于索引密钥更新而在页面之间移动时出现的问题类别,这些分配有序扫描也很容易受到页面拆分问题的影响(如果文件中新分配的页面在文件中比点较早,则可以错过行如果已经扫描或读取已经扫描的页面已经扫描或读取两次,如果已扫描的页面分为文件中的后面页面)。

至少对于简单(单表)查询,可以阻止使用这些扫描并在 nolock 通过简单地添加 ORDER BY index_key 到查询,以便 Ordered 属性 IndexScantrue.

但是,如果您的报告申请不需要绝对精确的数字,并且可以忍受此类不一致的更大可能性,则可以接受。

但是,当然,您不应该在所有查询中都将其搅动,希望这是一个神奇的“涡轮”按钮。以及在该隔离级别遇到异常结果或根本没有结果的较大概率(“由于数据移动,无法继续使用Nolock继续扫描” nolock 可能会更糟.

您的客户忍受不一致的报告吗?如果答案是否定的,则不应使用nolock-在并发下可能会获得错误的结果。我写了一些例子 这里, 这里, , 和 这里. 。这些示例表明,读取和重复阅读的输出不一致,但是您也可以调整它们并通过Nolock获得错误的结果。

我创建的大多数报告都不在当前数据上运行。大多数客户正在运行报告是昨天的数据。如果是这样,您的答案会改变吗?

如果是这样,那么您还有一个可能的选择:
而不是在生产数据库上运行查询,而是用锁和 NOLOCK, ,您可以从生产数据库的副本中运行报告。

您可以将其设置为 每天晚上自动从备份恢复.
显然,您的报告正在客户网站上的服务器上运行,因此我不知道设置是否对您来说是可行的解决方案。
(但再说一次...他们还是应该有备份,所以您只需要一些服务器即可修复它们)

我是内部开发人员,所以这对我来说更容易,因为我对服务器和数据库有完全控制。

您至少可以为仅需要昨天及以上数据的报告做到这一点。也许某些报告必须保留在生产数据库中,但是至少您将某些负载移至另一个数据库(甚至更好,另一台服务器)。

我在工作中也有相同的情况:
我们正在使用这样的生产数据库副本来用于几乎所有报告内容,但是有一些疑问需要今天的数据。

许可以下: CC-BY-SA归因
不隶属于 dba.stackexchange
scroll top