某个特定的存储过程在SQL 2008中执行会遇到以下错误:
Msg 701, Level 17, State 123, Procedure GetAllRevisions_Monthly, Line 22
There is insufficient system memory in resource pool 'internal' to run this query.
Msg 701, Level 17, State 65, Procedure GetAllRevisions_Monthly, Line 22
There is insufficient system memory in resource pool 'internal' to run this query.
我们可以从问题的描述和现象中得到什么信息:
首先我们需要确认几个问题:
<!--[if !supportLists]-->1. <!--[endif]-->这个存储过程在单独执行的时候会不会遇到这个错误。也就是说,在一个没有其他用户访问的时候,单独执行这个存储过程。这一点非常重要,可以帮助我们确认SQL Server是由于总体的工作负载太高而导致无法分配足够内存执行语句,还是这条语句本身执行的问题。
<!--[if !supportLists]-->2. <!--[endif]-->这个存储过程是不是每次执行都会遇到这个错误。
在这个案例中的情形,该存储过程即使在单一用户访问的时候执行,也会遇到这样的错误,并且在每次执行的时候都会出现同样的错。需要注意的是,这个存储过程在第一次执行的时候,会执行一分钟左右以后,报出错误信息。而当第二次执行和以后多次执行的时候,都是不到一秒立即报错。
这里额外的介绍一下对于语句和存储过程,多次测试的时候需要注意的问题:任何语句在第一次执行的时候,会生成执行计划并且将执行计划缓存的SQL Server的内存中,而第二次或者以后多次执行,只要之前存放的执行计划没有从内存中清除,语句和存储过程是会重用原有存储的执行计划。因此,如果我们希望每次测试都能实现语句第一次执行时候的效果,我们需要每次执行之前将缓存的执行计划手工清除。DBCC freeprocache这个命令可以帮助我们清除所有缓存的执行计划。
这个案例的测试情况如下:
Dbcc freeproccache
执行存储过程,用时一分钟,报错。
再次执行存储过程,立刻返回错误。
Dbcc freeproccahe
执行存储过程,用时一分钟,报错。
再次执行存储过程,立刻返回错误。
通过这个现象,可以得出结论,首次执行一分钟以后报错,是因为对该存储过程进行了编译和生成执行计划。而后续执行时立即报错,是重用了存储过程缓存的执行计划。也就是说,这个存储过程的解析和编译过程是没有问题的。但是一旦按照编译的执行计划执行的时候,就遇到了内存不足的问题。
以上是我们通过问题的现象和描述分析出问题的可能性。接下来我们就进入重现问题收集log的阶段。
对于内存不足的错误,我们需要收集哪些信息用以诊断呢?</