SQL Server内存问题与AWE
把和SQL Server内存和AWE相关问题的基本内容整理了一下。
1. SQL Server内存基本概念
在涉及SQL Server内存时有几个比较重要的术语:
Buffer Pool (BPool)
SQL Server使用的几个分散的地址空间,内部进程使用,包括存储编译,执行计划,创建索引,申请指针。
MemToLeave
SQL Server在启动时就保留的连续地址空间,供进程空间内的大于8KB的外部组件用,诸如扩展过程,COM/OLE自动化组件,连接服务器等。
Reserved
保留的地址空间,以供未来使用。
Committed
进程现在使用的地址空间,可能是物理RAM也可能是页面文件空间。
Allocation
把内存资源给消费者。
SQL Server在初始化过程中干了些什么?
1. 计算并保留MemToLeave
SQL7.0是256M,SQL Server 2000是384M,2005和2008估计也差不多。
2. 检查OS支持的最小物理内存和VAS,分配以下空间:
a)buffer头
b)BPool
c)对BPool跟踪的array
3. 把LazyWriter归零
LazyWriter定期检查BPool,看是要增加还是缩减。(因为大概要间隔60秒,所以看上去比较懒。。。真形象)
4. 释放保留的MemToLeave,保证MemToLeave地址空间连续
SQL Server不会在一上来就保留Min Server Memory,但只要系统一旦达到Min Server Memory设置就不会再次低于那个设置。对于Intel系统,SQL Server至少会留4MB内存。如果达不到,那么SQL Server就会将内存释放给OS。如果没需求SQL Server不会乱吃内存,不过一般情况下也不会吐内存出来,为了避免性能明显下降。
2. VAS与AWE
当SQL Server可用的内存在3-4GB以下,SQL Server可以完全用Virtual Address Space(虚拟地址空间,VAS)。2G为用户模式用,2G为系统(内核模式)用。就是说在这种情况下SQL Server最多用2GB内存(当然因为还有其他应用程序,一般只能用不到2G,比如1.6G)。例如在我的32位测试机上,运行DBCC MemoryStatus,结果如下:
Memory Manager KB
VM Reserved 1683800
VM Committed 293084
保留的virtual address space为1.68GB左右,占用的为290MB左右。
对于3G以上内存的机器就要用AWE(Address Windowing Extensions),允许映射到额外的内存上,上限64GB。
应用了AWE,从Task Manager看,SQL Server进程始终只用了256MB内存,被AWE用的内存不显示。所以看SQL Server占用的内存最方便的方法是在性能监视器(Performance Monitor)中的SQLServer: Memory Manager - Total Server Memory (KB)。
也可以通过DBCC MEMORYSTATUS或如下查询来查看:
SELECT * FROM sys.dm_os_performance_counters
WHERE counter_name IN ('Target Server Memory (KB)','Total Server Memory (KB)')
Target Server Memory (KB)就是最多可以吃多少,Total Server Memory (KB)就是目前吃了多少。
SQL Server进程占用率也可以用下面的查询:
SELECT *
FROM sys.dm_os_ring_buffers
WHERE ring_buffer_type = 'RING_BUFFER_RESOURCE_MONITOR'
启用AWE有三步:
1. 在boot.ini内增加/pae 允许Windows Server访问更多内存(最多16GB)
2. 给SQL Server进程赋予“Lock Pages in Memory”
3. 将配置中的“AWE Enabled”设置为1
对于Windows Server 2003,如果启用了AWE,SQL Server总是会使用它并动态管理。在启动时它会分配用作启动工作负载的内存,接着就会看自己的需求有多少内存吃多少,直到到达“Max Server Memory”。如果SQL Server遇到内存压力,会尽可能释放内存,直到“Min Server Memory”。
建议设置“Max Server Memory”以保证其他进程有内存用,对于32GB内存的可以留2G,对于64GB内存的可以留4G。如果同时有多个实例存在,更需要防止一个实例吞掉了过多内存。
AWE对于64位机器不是必须的。不过还是建议给运行SQL Server进程的用户帐号“Lock Pages in Memory”权限,
防止SQL Server内存不够写就写到磁盘上。对于64位服务器,默认使用AWE,所以如下查询可能会返回非零值:
Select sum(awe_allocated_kb) / 1024 as [AWE allocated, Mb]
From sys.dm_os_memory_clerks
目的是避免working set trimming。
3. SQL Server内存问题
当配置SQL Server时,知道它如何应对内存压力非常重要。内存压力分为两大类:VAS和物理内存。物理内存压力直接从OS就可以看出来,因此也可以称作外部内存压力。也可能是它自己的进程导致的,因此也可以称作内部内存压力。
SQLOS管理内存压力的整体架构如下:
Resource Monitor
/ | \
Low Physical Internal/External Low VAS High Physical Internal/External |
Resource Monitor(RM)是一切的核心,一有动静马上获知,广播到memory clerks。
先暂时整理到这里。
之所以研究这个问题是由于一个case,客户的64位SQL Server会出现AWE Allocated突然从6G(MAX Server Memory)跌到2G(Min Server Memory),再过了数个小时之后SQL Agent出现Virtual Memory Too Low导致任务失败。我研究了很长时间也没有获得结论,只好Escalate掉。目前楼上Team的工程师怀疑是系统的问题导致强制回收内存,让客户使用perfmon log和adplus(ADPlus 是 Microsoft 产品支持服务 (PSS) 提供的一个工具,它可以解决停止响应(挂起)或失败(崩溃)的任何进程或应用程序的问题。)收集系统的信息。
还有另外一个也是和内存有关的case,客户机器的4G内存莫名其妙地被SQL Server进程吃掉了2.9G,但进程占用的CPU占用,想知道是为什么。这个现在正在帮忙收集信息中。客户好像关于这个了解的比我还少,能稍微最近做的一个内存紧张一个Report Viewer优化一个Data Mining都没能解决在拖了很久之后只好Escalate,真受打击。。。好吧,专心做剩下的Discuz!NT的case,知道自己几量重后只好用努力来弥补了。
参考内容:
SQL Server 2005 and AWE Memory
http://www.jimmcleod.net/blog/index.php/2008/06/03/sql-server-2005-and-awe-memory/
AWE related
http://blogs.msdn.com/slavao/archive/2005/11/15/493019.aspx
http://blogs.msdn.com/slavao/archive/2005/04/29/413425.aspx
http://support.microsoft.com/kb/918483
SQLOS's memory manager: responding to memory pressure
http://blogs.msdn.com/slavao/archive/2005/02/19/376714.aspx
SQL Server Memory
http://www.sqljunkies.ddj.com/Tutorial/0D4FF40A-695C-4327-A41B-F9F2FE2D58F6.scuk
Slava Oks's WebLog
http://blogs.msdn.com/slavao/archive/tags/default.aspx