我有一个4节点AG设置,如下所示:
所有节点的VM硬件配置:
- Microsoft SQL Server 2017企业版(RTM-CU14)(KB4484710)
- 16个vCPU
- 356 GB RAM(长话短说...)
- 最大并行度:1(根据应用程序供应商的要求)
- 并行成本阈值:50
- 服务器最大内存(MB):338944(331 GB)
AG配置:
- 节点1:主节点或同步提交不可读的辅助节点,配置为自动故障转移
- 节点2:主节点或同步提交不可读的辅助节点,配置为自动故障转移
- 节点3:具有异步提交的可读辅助集,配置为手动故障转移
- 节点4:具有异步提交的可读辅助节点集,配置为手动故障转移
有疑问的查询:
此查询没有什么疯狂的,它提供了应用程序内各种队列中未完成工作项的摘要。您可以从下面的执行计划链接之一查看代码。
主节点上的执行行为:
在主要节点上执行时,执行时间通常约为1秒标记。这是执行计划,以下是从主节点从STATISTICS IO和STATISTICS TIME捕获的统计信息:
(347 rows affected)
Table 'Worktable'. Scan count 647, logical reads 2491, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'workitemlc'. Scan count 300, logical reads 7125, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Workfile'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'schedulertask'. Scan count 1, logical reads 29, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'wfschedulertask'. Scan count 1, logical reads 9, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'schedulerservice'. Scan count 1, logical reads 12, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'schedulerworkerpool'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'itemlc'. Scan count 1, logical reads 26372, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(1 row affected)
SQL Server Execution Times:
CPU time = 500 ms, elapsed time = 656 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
只读辅助节点上的执行行为:
在任一只读辅助节点(即节点3或节点4)上执行时,此查询使用相同的执行计划(这是一个不同的计划链接),并且显示大致相同的执行状态(例如,可能会有更多页面)扫描,因为这些结果总是在变化),但是除了CPU时间外,它们看起来非常相似。以下是从只读辅助节点从STATISTICS IO和STATISTICS TIME捕获的统计信息:
(347 rows affected)
Table 'Worktable'. Scan count 647, logical reads 2491, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'workitemlc'. Scan count 300, logical reads 7125, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Workfile'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'schedulertask'. Scan count 1, logical reads 29, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'wfschedulertask'. Scan count 1, logical reads 9, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'schedulerservice'. Scan count 1, logical reads 12, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'schedulerworkerpool'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'itemlc'. Scan count 1, logical reads 26372, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(1 row affected)
SQL Server Execution Times:
CPU time = 55719 ms, elapsed time = 56335 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
其他详情:
在执行此查询的同时sp_WhoIsActive
,我也在Paul Randal的WaitingTasks.sql
辅助脚本上运行了这两个脚本,但是我看不到发生任何等待,这实在令人沮丧:
这似乎也不是AG延迟的情况,因为“同步”状态实际上非常好:
--https://sqlperformance.com/2015/08/monitoring/availability-group-replica-sync
SELECT
ar.replica_server_name,
adc.database_name,
ag.name AS ag_name,
drs.is_local,
drs.synchronization_state_desc,
drs.synchronization_health_desc,
--drs.last_hardened_lsn,
--drs.last_hardened_time,
drs.last_redone_time,
drs.redo_queue_size,
drs.redo_rate,
(drs.redo_queue_size / drs.redo_rate) / 60.0 AS est_redo_completion_time_min,
drs.last_commit_lsn,
drs.last_commit_time
FROM sys.dm_hadr_database_replica_states AS drs
INNER JOIN sys.availability_databases_cluster AS adc
ON drs.group_id = adc.group_id AND
drs.group_database_id = adc.group_database_id
INNER JOIN sys.availability_groups AS ag
ON ag.group_id = drs.group_id
INNER JOIN sys.availability_replicas AS ar
ON drs.group_id = ar.group_id AND
drs.replica_id = ar.replica_id
ORDER BY
ag.name,
ar.replica_server_name,
adc.database_name;
该查询似乎是最严重的犯罪者。其他在主节点上也花费亚秒级时间的查询在辅助节点上可能花费1-5秒,并且这种行为虽然没有那么严重,但确实引起了问题。
最后,我还查看了服务器,并检查了诸如A / V扫描之类的外部进程,生成意外I / O的外部作业等,并且空手而归。我认为这不是由SQL Server进程之外的任何原因引起的。
问题:
我只是在中午的时候,已经有很长的一天了,所以我怀疑我这里缺少明显的东西。要么是因为我们配置不正确,要么是由于我们多次致电与该环境有关的供应商和MS,这是有可能的。
对于我的所有调查,我似乎都无法找到导致这种性能差异的原因。我希望在辅助节点上看到某种等待,但是什么也没有。如何进一步解决此问题以找出根本原因?有没有人以前见过这种行为,并找到了解决方法?
更新#1
将第三个节点(只读副本之一)的状态交换为不可读,然后又恢复为可读作为测试后,该副本仍由开放事务处理,所有客户端查询都将显示HADR_DATABASE_WAIT_FOR_TRANSITION_TO_VERSIONING
等待。
运行DBCC OPENTRAN
命令会产生以下结果:
Oldest active transaction:
SPID (server process ID): 420s
UID (user ID) : -1
Name : QDS nested transaction
LSN : (941189:33148:8)
Start time : May 7 2019 12:54:06:753PM
SID : 0x0
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
在中查找此SPID时sp_who2
,将其显示为一个BACKGROUND
进程,并将其QUERY STORE BACK
列为命令。
虽然我们都能够采取的TLog备份,我想我们正在运行到的类似的功能这个解决的错误,所以我打算与MS关于这一具体问题今天开了罚单。
根据该票证的结果,我将尝试根据Joe的建议捕获呼叫堆栈跟踪并查看我们的去向。
最终更新(问题自行解决)
在使查询存储事务的开放时间超过52小时(如上所示)之后,AG决定自动进行故障转移。在此之前,我确实做了一些其他指标。每此链接,由Sean提供的,有问题的数据库的人不得不专门为这个数据库非常大的版本库,特别是在一个点上我已经记录在1651360个页面reserved_page_count
场和13210880的reserved_space_kb
值。
根据ERRORLOGs,故障转移发生在5分钟的与QDS base transaction
和QDS nested transaction
事务相关的事务强化失败之后。
在我的情况下,故障转移确实造成了大约10分钟的停机。该数据库的大小约为6TB,并且非常活跃,因此我认为这实际上非常好。当新的主节点在此期间处于联机状态时,没有客户端查询可以完成,因为它们都在等待QDS_LOADDB
等待类型。
故障转移后,版本存储号减少为的176 reserved_page_count
和的1408 reserved_space_kb
。对辅助只读副本的查询也开始像从主副本运行一样快地执行,因此由于故障转移,行为似乎完全消失了。
QDS_LOADDB
-如果将来想避免这种情况,但仍保持Query Store处于打开状态,则可以使用Microsoft建议的这些跟踪标志。特别是7752将允许查询在查询存储初始化之前执行(因此您可能会错过一些查询,但您的数据库将启动)。
7752
看起来特别有用。谢谢你的提示!