深入SQLSERVER2000的内存管理机制(三)

<script type="text/javascript"><!-- google_ad_client = "pub-2947489232296736"; /* 728x15, 创建于 08-4-23MSDN */ google_ad_slot = "3624277373"; google_ad_width = 728; google_ad_height = 15; //--> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
<script type="text/javascript"><!-- google_ad_client = "pub-2947489232296736"; /* 160x600, 创建于 08-4-23MSDN */ google_ad_slot = "4367022601"; google_ad_width = 160; google_ad_height = 600; //--> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>

内存区域

是分2块区域来组织内存分配,分别是Bpool(缓冲池区)和MemToLeave(内存释放区),如果你使用AWE内存,那么实际上有第三个区:WindowsAWE支持的高于3GB的物理内存区。

缓冲池区是这3块内存区中最卓越的,是SQLSERVER最初分配的缓冲池供最初的数据页和索引页使用,并且被用来分配小于8K的内存。MemToLeave是由虚拟内存空间组成包括在用户内存空间没有被缓冲池区使用的内存空间之中。WindowsAWE调用3GB以上内存空间的函数作为缓冲池区的扩展可以提供额外的内存空间缓存数据页和索引页。

当你启动SQLSERVER时,缓冲池区的上限是根据机器中物理内存推算或用户内存空间的大小。一旦缓冲池区的大小被确定,内存释放区就紧随其后,不至于被后面的缓冲池区保留部分划分成分散的碎片。然后缓冲池区又在内存释放区旁边,使用32块单独的保留区运行DLL文件和其他在缓冲池区被预定时SQLSERVER中使用的虚拟内存空间。当缓冲池区被预留后,内存释放区被释放。这段区域被SQLSERVER内部用来扩展8K的数据页和分配给其他外部应用(就像:内存消费者是SQLSERVER主要引擎以外的SQLSERVER进程),比如:OLEDBproviders,COM对象等等.

因此,当SQLSERVER已经启动,Bpool(缓冲池区)就被预留,但不提交,同时在该进程在虚拟内存空间内的MemToLeave(内存释放区)其实是空闲区域.如果你通过性能分析器的VirtualBytesPerform计数器,在SQLSERVER启动后看SQLSERVER的进程,你会看到它可以反映Bpool(缓冲池区)预留区.我看到人们有些惊慌,因为这个数值比较高—毕竟,它反映的不是本机器的总共物理内存就是最大的用户内存空间减去MemToLeave(内存释放区).这是不用担心的,比较而言这只是保留区,没有提交的空间.就如我前面所述,保留空间只是地址空间—并没有真实的物理内存存储直到内存空间被提交.随着时间的过去,内存空间被提交,Bpool(缓冲池区)将会增加,知道该SERVER原始启动时确定的上限.

监控SQLSERVER虚拟内存的使用

    你可以通过SQLSERVER:BufferManager/TargetPagesPerform计数器跟踪Bpool(缓冲池区)确定的最大空间.因为SERVER不同的部分需要内存,Bpool(缓冲池区)提交8K大小的页(这是原始保留的直到提交的大小到达确定目标).你可以通过SQLSERVER:BufferManager/TotalPagesPerform计数器跟踪Bpool(缓冲池区)使用的提交虚拟内存,你可以通过PivateBytes计数器跟踪SQLSERVER进程使用的全部提交的虚拟内存.

因为,大部分的SQLSERVER的虚拟内存的使用是来自于Bpool(缓冲池区),通过上面2个计数器可以知道.一般而言增长和平稳是一前一后地.(请牢记:当应用程序启动了对AWE的支持,PivateBytes计数器不能反映总体SQLSERVER内存使用情况).如果TotalPagesPerform计数器是水平的而PivateBytes计数器是向上倾斜的,这一般表示正在从MemToLeave(内存释放区)分配新的内存.这个分配过程会正常结束—例如:在SERVER中分配相关联的线程堆栈作为附加的工作线程,这也有可能是一个内部测COM对象或XPROC的内存泄漏.如果一个程序因为MemToLeave(内存释放区)耗尽而用完虚拟内存空间,这是由于内存泄漏或内存过度消费.(或者在MemToLeave(内存释放区)中最大空闲块降低到默认线程堆栈0.5MB以下),这样SERVER就不能产生新的工作线程,即使在sp_configuremaxworkerthreads的值没有到.在这种情况下,如果SERVER需要产生新的工作线程来执行一个工作请求—比如:处理一个对SERVER的新的连接请求,这些工作将会延迟,直到SERVER可以产生新的线程或其他的线程可以使用.这样,在有足够的MemToLeave(内存释放区)释放或其他的工作线程可以有效的处理连接之前,系统会阻止一个用户连接到SERVER,因为这个连接会超时中止(timeout).1

<script type="text/javascript"><!-- google_ad_client = "pub-2947489232296736"; /* 728x15, 创建于 08-4-23MSDN */ google_ad_slot = "3624277373"; google_ad_width = 728; google_ad_height = 15; //--> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
<script type="text/javascript"><!-- google_ad_client = "pub-2947489232296736"; /* 160x600, 创建于 08-4-23MSDN */ google_ad_slot = "4367022601"; google_ad_width = 160; google_ad_height = 600; //--> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
阅读更多
个人分类: 数据库
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭