我正在进行浸泡测试,并不断遇到一个我过去从未见过的奇怪问题。我花了很长时间来调查这个问题,到目前为止还没有成为它的底层。
在测试过程中的某个时刻(有时1小时,其他时间超过4小时),SQL Server机器开始最大化它的CPU。这总是对应于DB高速缓存的急剧减少和可用内存的增加。
这些迹象显然指向内存压力,似乎我有时会通过运行特别繁重的查询来触发此事件。
我可以理解为什么计划缓存会被刷新,但是这方面令我感到困惑的是:
在缓存刷新之后,缓存命中率仍然是OK-ish,~90%但是这远低于我在刷新之前看到的~99%并且真正伤害了CPU。
在刷新之前,一段高速缓存未命中,插入和命中看起来很正常。预先刷新我看到的唯一问题是非参数化的即席查询,它经常被插入到缓存中,但即使这样,它也是一个非常简单的查询,它具有较低的成本,因此可以预期这些查询将从前面的缓存中刷新大多数其他事情。
后刷新我看到非常多的插入,紧接着是同一个对象(即存储过程)上的大量未命中,因此缓存的内存消耗仍然很低。
从下面我的计数器镜头中的黄线可以看出,缓存内存使用率下降并保持低位,但可用内存(皇家蓝)保持相当高。
修改
在研究这个问题以获得另一个好处,同时一个不断出现的模式是,如果我将服务器推到它的极限一小段时间(增加负载高于浸泡测试产生的那个),那么SQL Server似乎已经进入它本身无法恢复的混乱局面。
当达到最大压力点时,服务器的连接数量急剧增加(我假设由于它无法足够快地处理请求,因此需要新的连接来处理“常量”流量请求)。然后,这个积压工作对服务器施加了进一步的压力,它似乎无法从中恢复。
现在,我仍然对指标感到困惑。如果新连接似乎占用内存,进一步减慢处理速度,导致新连接等,我可以接受这纯粹是一个服务器资源问题。我看到的是有足够的可用内存但SQL Server不是将它用于计划缓存。正因为如此,它花费了更多的时间进行编译,增加CPU和事物失控。
感觉连接是这个问题的关键部分。如前所述,如果我重新开始测试,一切都会恢复正常。我已经发现将数据库置于单用户模式几秒钟以便所有与测试相关的连接中断,等待几秒钟然后返回多用户模式解决了这个问题。我试过基于SPID杀死所有活动连接,但是为了让服务器恢复并开始正确使用计划缓存,似乎需要暂停几秒钟。
请参阅我的计数器下面的截图。我试图将服务器推到顶部~02:33:15然后我在~02:34:30设置为单用户模式,然后在几秒后设置为多用户模式。
紫色线是用户连接,厚红色是汇编p / s,亮绿色是缓存,aqua连接内存,灰色/棕色是空闲内存。
答案 0 :(得分:0)
好吧,这是一条漫长的循环道路,但我目前对此的最佳答案是,这个问题是由于资源限制以及SQL Server针对我的特定情况的计划缓存做出的不幸选择。我不是说SQL Server是错的,只是因为我的需求在这个时候我认为它没有做出正确的决定。
我已经调整了我的浸泡测试,以便如果数据库服务器受到压力,它会拉动一些控制并丢弃一些连接,直到服务器恢复控制并且可以重新建立其他连接为止。 SQL Server恢复顺序的过程可能需要几分钟但确实会发生!
似乎服务器正处于一个恶性循环中,它正面临压力,放弃缓存的计划,然后不得不花费更多的时间来重新编译这些计划,而不是通过首先放弃它们获得的。这导致事情失控,一切都停止了。
在我的特定情况下,存在非常高的缓存命中率(高于99.5%)并且由于浸泡测试基本上对于用户的负载重复执行相同的事情数小时,缓存被很好地使用。如果缓存没有得到很好的使用,那么SQL Server很可能通过放弃计划做出了正确的选择,但我不认为它是在这里做的。