存储引擎自调整
sql server 是如何分配内存的
32bit地址空间的限制
用户模式vas分配和virtualalloc
非boffer pool 分配内存(保留内存)
VAS调整
AWE
启动参数-g
诊断内存压力
内存相关计数器
SQL Server :Buffer Manager
buffer cache hit ratio
page life expectancy
Free Pages
Free list stalls/sec
lazy write/sec
SQL Server:memory Manager
total server memory 和 target server memory
memory grants outstanding
memory grants pending
内存相关的DMV
内存相关问题
分页问题
因为lock pages 和没有设置服务器最大内存导致系统不稳定
701错误和 FAILED_VIRTUAL_RESERVE
多实例下的内存设置
总结
内存的分配和使用在网上一直是讨论的话题。对sql server 来说使用了内存但是不释放是很正常的事情,和其他的应用程序是不一样的,导致一些用户认为sql server确实内存但事实并非如此。
存储引擎自调整
从sql server 2005开始,内存的管理就是动态的,与其他关系型数据库不同使用已经调整好的内存空间。如plan cache 是全部的并且自动的,引擎控制根据当前数据库的负载和其他活动信息来控制plan chache内存。sql server 虽然缺少内存的控制方法,但是还有有参数可以设置内存的,如操作系统的版本,内存的大小和处理器的体系结构。
sql server 是如何分配内存的
第一反应就是查看windows任务管理关于sql server 的内存使用情况,一看到sql server 占用了很大的内存就可能会认为sql server 缺少内存,但是缺少内存和占用很大内存其实是没什么关系的。sql server是被设计为大内存使用的,如buffer cache,存放了大量的数据页,为了减少io,提高性能。通常,不管你提供了多少内存sql server 都能使用光,除非你接到一个来自操作系统的memory low通知,sql server 就会自动调节减小内存,通知有2中:
memory high:通知sql server可以增加内存的使用量
memory low:通知sql server 释放内存
如果windows 不通知,那么sql server 就不会增加或减少内存,在windows 2003 和 sql server 2005 以前的版本是没有的。有一篇关于sqlos中内存的文章介绍了不同类型的内存压力,大致如下:

sql server 最大内存使用量由以下几点要素:
1.安装的物理内存数量
2.操作系统的最大内存限制
3.sql server 体系结构,32b,64b
4.sql server 配置项
5.sql server 版本
32bit地址空间的限制
对于sql server 32位最大的影响就是32位的地址空间,也就是最大4g而且包含内核模式和用户模式。用户模式和内核模式各2个g。主要我们讨论一下几点
1.sql server 用户模式如何分配内存
2.非buffer pool的保留空间
3.用户模式使用3g 内存
4.sql server 如何使用大于4g内存,data cache调用awe内存。
接下来主要讲的都是32bit 下内存使用的限制和64bit关系不大。
用户模式vas分配和virtualalloc
sql server 为用户默哀是保留了2g的内存地址,sql server 用户模式需要内存时,通过调用virtualalloc 分配内存并返回32位的指针,因为地址空间的限制,所以sql server 只能使用2g内存。
通过virtualalloc分配的内存并不一定是实际的物理内存,不管安装了多少物理内存,sqlserver都是2g的地址使用空间。windows也保证sql server 和其他应用程序使用的内存,不会超过实际物理内存和页面文件的总容量。如果总共安装的内存少于2g,那么sql server 就会又物理内存的限制,sql server buffer pool的内存也不会超过安装的内存数量。virtualalloc 分配的内存都是页模式的,也就是如果出现内存压力windows 就可以直接把内存写入到磁盘中。
非boffer pool 分配内存(保留内存)
如果sql server 请求大于8k的连续内存的时候,会使用多页分配器分配内存。backup buffers 是非buffer pool分配的最大的一个,需要的内存是 maxtransfersize * backupbuffercount 在正常的备份下,需要16个backup buffer,每一个buffer又4m的内存。所以会吃掉64m的非buffer pool 内存。为了保证有住够非buffer pool,32b的sql server 在启动的时候会保留一部分内存。一旦有保留内存,那么buffer pool的内存空间会是安装的空间减去保留的空间。对于2005和2008保留空间为 maxworkerthreads*0.5mb+256mb(默认保留空间大小),maxworkerthreads = (processprcount-4)+256。在2000 中maxworkerthreads = 256,按这个计算保留空间至少是384MB,但是通常少于432mb。保留空间的参数在sql server 启动参数内设置,标记为-g,可是适当在计算出来的结果上增加内存。sql server 一共2g的地址空间减去保留的,大概剩下1.6G供buffer pool 使用。对于超过4gb的内存可以使用awe来分配内存。
VAS调整
对于4g的内存,系统可以修改内核的地址空间使用率把1:1,变为1:3。这个叫做4g调整,这样就减少了内核模式下的地址空间,导致了PTE减小,pte是虚拟内存和物理内存的映射,一但减小,sql server 总共可使用的内存也就背减少了。所以在调整的时候要谨慎。在windows 2008下可以使用bcdedit /set 命令设置increaseuserva 可以设置从 2048 到 3072的值。在2000 到 2003 可以使用/3g的标签来开启。
AWE
如果安装了超过了4个的内存,那么就可以使用awe,当然windows 必须支持才能使用。开启pae,系统最多能够使用64G内存。在内存分配上因为使用virtualalloc分配内存会有限制,那么就改用allocateuserphysicalpage来分配内存,一旦被分配那么内存页被锁住,无法交换到交换文件。当启用awe后所有的datacache使用过awe分配内存还有就是 plancache也是。要启用awe那么pae就必须被设置,还有在sql server 的awe enabled 参数sql server 的启动用户必须有lock pages 权限。因为awe内存无法被交换出去,所以设置最大内存数量很偶必要,使得sql server 内存使用量得到限制,不会无限期的增长影响其他应用程序和系统内存的使用问题。在系统中如果你的内存少于16g,你可以使用前面提到的awe+4gt的方式,但是不推荐因为如果你一旦设置了4gt,windows 可管理内存从64g下降到了16g yinwei 4gt减少了pte的大小。
启动参数