0

我们正在使用 SQL Server 2012 EE,但目前没有在 R/O 镜像上运行查询的选项,尽管这是我的长期目标,但我担心在这种情况下我也可能会遇到以下问题,因为镜像会还要更新我正在查询的数据。

我有一个视图,它连接来自两个数据库的多个表,并用于从现有数据开具发票。其中三个表也被正在进行的事务主动更新。运行使用此视图的报告以前不是问题,但现在我们的数据库变得越来越大,我遇到了一些超时问题。首先,查询超时,所以我将命令超时设置为 0 并重新运行查询,该查询将所有 4 个 CPU 100% 挂钩 90 分钟,然后我将其杀死。在此期间,活动交易没有问题。我查看了查询,发现我加入的一个字段没有被索引,因此在该字段上创建了一个索引,重新运行报告,然后在三分钟内完成,所有 CPU 都很忙,但根本没有挂钩。两次查询的数据量相同。我想问题解决了。当然后来,我的老板运行了一个类似的查询,可能有更多数据,但可能不会更多,当他的查询运行时,我们的实时事务开始 100% 超时。在那段时间里,我没有机会看到 CPU 的使用情况。

所以我的问题有两个:

  1. 鉴于我必须使用实时和活动数据库,运行长 R/O 查询以使活动事务仍然可以继续的正确方法是什么?我正在考虑 NO LOCK,但希望有更好的标准做法。

  2. 什么可能导致 sqlserver 以 100% 繁忙的速度将 4 个 CPU 挂起并且不会导致实时事务超时,但是当我的老板运行他的查询时,在我添加索引并且我的查询运行得更好之后,实时更新事务开始超时 100% ?

我知道这不是很多信息。我对 sql 分析和性能监控不是很熟悉,但这种行为似乎很奇怪,我希望最佳实践是正确的解决方法。

4

2 回答 2

2

SELECT事务隔离级别中查询的默认行为READ_COMMITTED是在查询执行期间获取共享锁以提供请求的数据一致性(仅读取提交的数据)。这些锁通常是行级的,并在读取每一行后立即在查询执行期间快速释放。页面和表级别的意图锁定也较少,可防止在读取数据时对其进行并发更新。根据执行计划的具体情况,甚至可能在查询期间在表级别持有共享锁,这将阻止在查询执行期间对表进行更新并导致读取器阻塞写入器。

设置READ_COMMITTED_SNAPSHOT数据库选项会导致 SQL Server 使用行版本控制而不是锁定来提供相同的读取一致性。行版本存储在 tempdb 中维护,因此当查询请求的行自查询开始后发生更改时,将返回最新提交的行版本。这种行版本控制行为避免了锁定,并在查询开始时有效地提供了数据库的语句级快照。读者不阻止作者,作者不阻止读者。不要将READ_COMMITTED_SNAPSHOT数据库选项与SNAPSHOT隔离级别混淆(常见错误)。

设置的缺点READ_COMMITTED_SNAPSHOT是额外的资源使用。启用数据库选项后,每行会产生额外的 14 字节存储开销。更新和删除将在 tempdb 中生成行版本。这些版本在最长运行查询期间需要 tempdb 空间,并且维护版本存储会产生开销。还要考虑您是否有依赖于 reader-block-writers 锁定行为的现有应用程序。尽管存在这种开销,但根据您的工作负载,并发优势可能会产生更好的整体性能,同时提供读取完整性。有关详细信息,请参阅http://technet.microsoft.com/en-us/library/ms188277.aspx

于 2014-10-04T14:42:05.263 回答
1

实际上,我决定在每个月初创建一个快照,以便进行报告。然后在不再需要报告时删除。这似乎工作正常。我可以对数据库还原做类似的事情,但工作量会稍微多一些。这允许不需要第二个 SQL EE 许可证,并允许我为实时事务运行不带锁定表的报告。

于 2014-10-03T22:35:39.240 回答