切换到 RCSI

Col*_*e W 9 sql-server isolation-level metrics

我工作的公司目前使用 SQL Server 数据库(通常是最新的企业版)用于我们开发的产品。

我会将它描述为一个 OLTP 数据库,它具有大量时间关键应用程序的读写密集程度。除此之外,根据同一 OLTP 数据库(单独问题)中的信息显示了大量报告和图形数据,这些数据以频繁的速率读取和写入许多相同的表。

我们通常会遇到发生阻塞的问题,并且通常最终会减慢时间关键应用程序的速度,甚至由于这些应用程序中的死锁而导致问题。这个问题的常见解决方案似乎通常是对nolock有问题的查询提出提示。老实说,我讨厌这个解决方案,很长一段时间以来,我一直认为这是尝试解决这个问题的错误方法,从我阅读的所有内容中,我得出了相同的结论。

一段时间以来,我一直试图说服我的团队 RCSI 是我们绝对可以从中受益的东西,特别是考虑到我们的数据库类型。他们似乎认为这是一个很大的风险,并且经常因为风险因素而推迟它,但我们继续遇到性能问题,我们只是nolock在暗示它。

  • 我如何帮助证明我们的数据库可以从使用 RCSI 中受益匪浅?
  • 是否有我可以基于我们在测试环境中转换为 RCSI 的实际生产数据库运行的性能测试?

我正在寻找一种向我们的团队展示具体指标的好方法,以最终说服他们我们应该转向这种方法。

Aar*_*and 8

我相信你知道,仅仅因为很多人使用NOLOCK不能使它成为一个好主意——毕竟,如果你回溯得足够远,很多人认为奴隶制、杀虫剂、石棉、含铅油漆和汽油等. 也是很棒的想法。

NOLOCK具有性能优势,但不是因为它不需要锁——这仅仅是因为它允许读取器忽略其他读取器或写入器采用的锁。NOLOCK根据谁对底层表做了什么,仍然可以阻止查询- 至少,Sch-S仍然需要锁。

但是缺点很多,并且在发生之前通常会被忽略——人们很高兴他们的查询“快速”——即使他们产生了不正确或不一致的数据,尤其是在他们没有注意到的情况下。使用NOLOCK/ READ UNCOMMITTED,您可以:

  • 读取同一行两次(您已读取的行在分配顺序扫描之前移动)
  • 完全跳过一行(您尚未阅读的行移动到扫描后面)
  • 读取可能永远不存在的未提交行
  • 由于扫描期间移动过多而导致错误
  • 在不同状态下读取一行中的不同列

该怎么办

您可以避免这些风险。默认的隔离级别 ( READ COMMITTED) 当然也不是没有数据一致性风险,只是NOLOCK增加了很多。

我看“快照”获得甩一下颇有几分-虽然他们可能听起来很相似,读取提交快照隔离是完全不同的快照隔离。肯德拉·利特尔 (Kendra Little)在这里有一篇详尽的文章,值得一读。

有人说“从来没有人因为使用快照隔离而被解雇”。我实际上可以想象那种事情很有可能发生的场景。快照隔离具有明显不同的语义,需要正确实施代码更改。更多变化=更多风险。

Read Committed Snapshot Isolation 可以在几乎没有代码更改的情况下实现,并且通常是人们建议您从NOLOCK/切换时的意思READ UNCOMMITTED。但是,也可以通过在数据库级别简单地启用 RCSI 来引入行为更改(请参阅Kendra 帖子中的第 3 项示例)。

虽然我个人认为 RCSI 比 好得多NOLOCK,但您需要记住,并不能保证性能会更好。RCSI 通过在 tempdb 中创建行的版本来工作,以便任何给定的会话在需要时都有自己的行副本。如果 tempdb 是您系统上的瓶颈,这可能不会那么顺利。此外,在数据库级别启用读提交快照意味着所有数据更改将每行增加 14 个字节。

这意味着,为了表明切换是值得的,如果当前不是最佳的,您应该充分装备 tempdb 以支持额外的负载,并且您需要准备好现有表需要更多的磁盘空间,并且,最终,在记忆中。如果 tempdb 已经饱和,或者您已经接近磁盘容量,或者内存已经耗尽,RCSI 可能无济于事。

(当然,还有其他方法可以提高性能,当然,如果NOLOCK不值得冒险,并且您没有 RCSI 的开销。例如,压缩可能是减少 I/O 的不错选择,当您有很多 CPU 开销。列存储索引对于特定的工作负载很有用。显然,细粒度的索引和查询调整可能是有益的。)

对于手头的问题:

与默认隔离级别相比,我建议您专注于确保您的查询返回正确的结果,而不会对性能造成明显影响比较NOLOCK并不公平,除非您对上述所有风险都感到非常满意。Kendra 的帖子详细介绍了衡量影响的一些细节,但基本上您希望对具有相同外部压力和并发性的相同工作负载进行前后测量:

  • 这些查询的查询时间有NOLOCK今天 ( sys.dm_exec_query_stats)
  • 整体性能指标 - 等待、I/O 延迟、tempdb 使用、内存使用,甚至页面预期寿命

您可以使用当前用于衡量性能的任何方法来执行此操作 - 如果您没有方法,我可能会建议使用监控工具可能是值得的,即使只是试用。(免责声明:我曾经为一个工作。)

没有什么神奇的“告诉我使用 RCSI 时我的工作量是否比不使用时更好”-这取决于性能的哪些方面对您很重要,哪些方面已经接近瓶颈,哪些方面将证明-在您的特定情况下- 总体收益或损失(再次假设其他一切保持不变)。

并且可能的情况是,您可以用定性的论据而不是(或除此之外)仅仅用“指标”来说服他们。

进一步阅读(上面重复了一些链接):


Mat*_*tum -6

在我当前的工作中,大多数数据库对象使用(NO LOCK)或READ UNCOMMITTED 隔离。我同意这是一个糟糕的解决方案,但如果你回溯得足够远,它会被经常使用。

我不熟悉缩写词 RCSI,但在谷歌搜索中我发现它指的是使用读提交快照隔离。是的,如果您遇到锁定和死锁问题,您应该使用快照隔离。

我认为证明这一点的最佳方法是创建生产系统的两个虚拟化克隆,在其中一个上使用快照隔离,在每个系统上模拟典型的使用模式,并验证它是否提高了性能。

或者只是在较低的环境中执行此操作,然后在验证其稳定后将更改迁移到生产环境。没有人因为使用快照隔离而被解雇。

  • 你说“验证它是否提高了性能”;您可能应该提到验证各种报告等的正确性,这些报告可能会受到隔离级别的任何变化的负面影响。我个人曾见过高层管理人员因放弃“NOLOCK”而产生的微妙变化而感到困惑。 (2认同)