SQL 2008+ NOLOCK 与 READPAST 对于报告准确性的注意事项

2023-12-21

了解最终的决策是业务决策,在 SQL 2008 R2 中运行的 NOLOCK 和 READPAST 之间的准确性考虑因素是什么?在与业务领域讨论变更之前,我希望能有更好的理解。

我继承了许多查询,用于创建管理报告的数据视图。 “WITH (NOLOCK)”被广泛使用,但不一致。读取的数据来自广泛使用的应用程序的生产服务器,并且不断更新。我们正在从 SQL 2005 服务器迁移到 SQL 2008 R2 服务器。这些报告希望数据比存档服务器上 24 小时的旧数据更新鲜。 NOLOCK 的使用暗示了过去的决定;存在冲突的可能性,并且一点点准确性损失是可以接受的。数据用于填充仪表板以供人类意识/决策。

所有查询都是 SELECT,数据视图登录具有只读访问权限。大多数查询都是单表,有少量 2 和 3 表连接。鉴于连接级别较低,WITH () 似乎是比 SET TRANSACTION ISOLATION LEVEL {} 更好的选择

表提示 (Transact-SQL)http://msdn.microsoft.com/en-us/library/ms187373.aspx http://msdn.microsoft.com/en-us/library/ms187373.aspx(以及有关 SO 的多个问题)表示,除了丢失锁定记录之外,NOLOCK 和/或 READUNCOMMITTED 还可能存在重复读取问题。

READPAST 看起来更准确,因为它只会错过锁定的记录,而不会出现重复。但我不确定它和NOLOCK之间丢失锁定记录的级别是否一致。

Tim Chapman 有一篇很好的文章比较了两者,但它写于 2007 年,大多数评论围绕 2000 年和 2005 年展开,其中一条评论表明 READPAST 在 2008 R2 中存在问题

参考

SELECT 语句中 NOLOCK 提示的效果 https://stackoverflow.com/questions/210171/effect-of-nolock-hint-in-select-statements

什么时候应该使用“with (nolock)” https://stackoverflow.com/questions/686724/sql-when-should-you-use-with-nolock

在 SQL Server 中使用 NOLOCK 和 READPAST 表提示(作者:Tim Chapman) http://www.techrepublic.com/article/using-nolock-and-readpast-table-hints-in-sql-server/6185492

Edit:

下面的两个答案建议使用快照隔离。快照隔离取决于数据库的设置,这个Q/Ahttps://serverfault.com/questions/117104/how-can-i-tell-if-snapshot-isolation-is-turned-on https://serverfault.com/questions/117104/how-can-i-tell-if-snapshot-isolation-is-turned-on描述如何查看数据库上的设置。我现在知道它已被禁用,我正在阅读主要应用程序数据库的报告。更改设置不是一个选项。 +- 几个百分点的准确度是可以接受的,但应用程序 (OLTP) 影响是不可接受的。大多数简单查询不需要考虑锁,但在某些极端情况下,需要考虑锁。随着 SQL 2005 快照隔离的出现,有关 SQL 2008 或更高版本中 NOLOCK 和 READPAST 行为的信息很少。然而它们仍然是我唯一的选择。


值得考虑的更好选择是为数据库本身启用 READ COMMITTED SNAPSHOT。这使用 tempdb 中的版本控制来捕获事务开始时表的状态。

关于 NOLOCK、READPAST 等各个方面的内容非常好,位于http://www.brentozar.com/archive/2013/01/implementing-snapshot-or-read-comfilled-snapshot-isolation-in-sql-server-a-guide/ http://www.brentozar.com/archive/2013/01/implementing-snapshot-or-read-committed-snapshot-isolation-in-sql-server-a-guide/

WITH (NOLOCK)如果您在从表中进行选择时有人正在更新表,则可能会提供不正确的结果。如果在读取表格时由于插入而发生分页,并且新页恰好超出了您已读取的点,WITH (NOLOCK)将从旧页面返回行,然后从新页面返回重复行。这只是一个简单的例子来说明原因(NOLOCK) is bad.

WITH (READPAST)当您从表中读取数据时,将跳过任何正在更新或插入的记录。对于繁忙的数据库来说,这两种选择都不好。

鉴于最近对您的问题的编辑,您指出您无法更改数据库设置READ COMMITTED SNAPSHOT,也许您应该考虑使用存储过程来收集报告数据,并使用以下命令在存储过程的开头设置事务隔离级别SET TRANSACTION ISOLATION LEVEL SNAPSHOT;。为此,您需要更改数据库选项“允许快照隔离”。

来自 SQL Server 在线书籍:

SNAPSHOT

指定事务中任何语句读取的数据将是事务开始时存在的数据的事务一致版本。事务只能识别在事务开始之前提交的数据修改。当前事务开始后其他事务所做的数据修改对于当前事务中执行的语句不可见。效果就好像事务中的语句获取了事务开始时存在的已提交数据的快照。

除恢复数据库外,SNAPSHOT 事务在读取数据时不会请求锁。 SNAPSHOT 事务读取数据不会阻止其他事务写入数据。写入数据的事务不会阻止 SNAPSHOT 事务读取数据。

在数据库恢复的回滚阶段,如果尝试读取被回滚的另一个事务锁定的数据,SNAPSHOT 事务将请求锁定。 SNAPSHOT 事务将被阻止,直到该事务被回滚。锁被授予后立即释放。

必须先将 ALLOW_SNAPSHOT_ISOLATION 数据库选项设置为 ON,然后才能启动使用 SNAPSHOT 隔离级别的事务。如果使用 SNAPSHOT 隔离级别的事务访问多个数据库中的数据,则必须在每个数据库中将 ALLOW_SNAPSHOT_ISOLATION 设置为 ON。

事务不能设置为以其他隔离级别开始的 SNAPSHOT 隔离级别;这样做将导致事务中止。如果事务在 SNAPSHOT 隔离级别下启动,您可以将其更改为另一个隔离级别,然后再返回到 SNAPSHOT。事务在第一次访问数据时启动。

在 SNAPSHOT 隔离级别下运行的事务可以查看该事务所做的更改。例如,如果事务对表执行 UPDATE,然后对同一表发出 SELECT 语句,则修改后的数据将包含在结果集中。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SQL 2008+ NOLOCK 与 READPAST 对于报告准确性的注意事项 的相关文章

随机推荐