Failed to reserve contiguous memory of Size 产生原因及解决办法
2006-06-23 14:41:40.72 spid77 WARNING: Failed to reserve contiguous memory of Size= 24641536.
2006-06-23 14:41:40.85 spid77 Buffer Distribution: Stolen=4800 Free=1744 Procedures=39391
Inram=0 Dirty=90621 Kept=0
I/O=0, Latched=99, Other=3063345
2006-06-23 14:41:40.85 spid77 Buffer Counts: Commited=3200000 Target=3200000 Hashed=3154065
InternalReservation=587 ExternalReservation=0 Min Free=1024 Visible= 173320
2006-06-23 14:41:40.85 spid77 Procedure Cache: TotalProcs=9555 TotalPages=39391 InUsePages=1031
2006-06-23 14:41:40.85 spid77 Dynamic Memory Manager: Stolen=44191 OS Reserved=7648
OS Committed=7619
OS In Use=7603
Query Plan=39088 Optimizer=0
General=4183
Utilities=140 Connection=7651
2006-06-23 14:41:40.85 spid77 Global Memory Objects: Resource=1617 Locks=313
SQLCache=1836 Replication=204
LockBytes=2 ServerGlobal=42
Xact=63
2006-06-23 14:41:40.85 spid77 Query Memory Manager: Grants=0 Waiting=0 Maximum=94533 Available=94533
2006-06-23 14:41:40.88 spid77 Error: 17803, Severity: 20, State: 12
2006-06-23 14:41:40.88 spid77 Insufficient memory available..
-----------------------------------------------------------------------------------------------------------------------------------------
问题:当我运行 Windows Server 2003 SP1 中的 SQL Server 2000 Enterprise Edition SP4 产品时,遇到了奇怪的内存不足异常。图 1 显示我从日志中获得的错误信息。
我的服务器内存很大 (32GB)。奇怪的是,该问题似乎是随机出现的,导致这一错误的存储过程似乎每 20 次执行就出现一到两次这类异常。
该服务器的性能计数器表明有大量可用内存。惰性写线程 (lazy writer) 没有足够快地向磁盘写入吗?当执行存储过程时,为什么需要如此大量的内存?是选择语句的数量问题还是因为使用了临时表?
解答:这一问题和机器的物理内存数量毫无关系。根据您的 boot.ini 设置方式,应用程序有 2 到 3 GB 的虚拟地址空间。虚拟地址空间是 32 位系统中的宝贵资源。默认方式下,缓冲池将消耗除了 384MB 的虚拟地址以外的所有空间。384MB 被分出来用于线程堆栈和从以下这样一些组件进行分配(第三方扩展存储过程、链接的服务 器、COM 组件),这类组件要么太大以至缓冲池无法支持,要么不知道如何从缓冲池分配
警告表明近 23MB 的分配失败。这种规模的分配成功与否取决于 384MB 块中其他分配的数量和位置。
您可能会考虑删除一些加载到系统中的第三方扩展存储过程,确定是否存在通过 sp_oacreate 或链接的服务器使用 COM 组件的现象。
当由于在您的存储过程中使用 FOR XML 子句而执行 SQL 存储过程(我们在此没有重复介绍)时,过程可能需要大量内存。然而,如果您想了解更详细的信息,Process\sqlservr\Virtual Bytes 将为您指示仍然有多少虚拟地址空间可用。还有一款称为 VMStat 的工具(包含在随 Jeffrey Richter 撰写的书籍“Programming Applications for Microsoft Windows”附赠的 CD 中),该工具可以确定最大虚拟地址块的大小。此分配中未涉及惰性写线程 (lazy writer);分配要使用的内存区域不在缓冲池中,对吗?
----------------------------------------------------------------------------------------------------------------------------------------
这篇Q&A来自
http://www.microsoft.com/technet/technetmag/issues/2006/11/SQLQA/default.aspx?loc=en原文的中文翻译上有较大的问题,“缓冲池将消耗除了 384MB 的虚拟地址以外的所有空间。”原文翻译正好与实际相反。e文不错的,还是建议看我给出上面的英文连接。
另外我还是要提一下sql2000中的那384MB的虚拟地址空间实际上就是微软提到的MemToLeave空间,这个空间主要有两部分组成,一个是线程桟区占据了255*桟区大小(也就是)512K,差不多为128MB;一个是扩展空间,这个值默认为256MB(指的是sql2000,sql7为 128MB),这个扩展空间值可以自己调整,调整的方式是在启动参数中加-g参数,具体怎样使用-g参数,可参照
http://support.microsoft.com/kb/316749/zh-cn。
最后说一下,这篇文章的意义,在新的mssql2005中,大家可以使用CLR来扩展mssql的外部存储,可以让mssql更加的灵活,但要注意了CLR 是使用MemToLeave空间来分配内存的,这部分内存是不同于bpool可以使用PAE方式直接使用物理内存,因此大家在不断的开拓mssql新功能时也要了解一下其内部的运作方式,以免日后生出很多的麻烦