系列参考自《SQL Server 2012实施与管理实战指南》,有删改。
从Windows层面看,SqlServer与word、Excel没什么不同,就是一个普通程序,Windows不会给它特殊照顾。如果os缺内存,SqlServer性能很可能受影响,但反过来,os不缺内存并不能保证SqlServer不缺内存。本节先了解Windows的内存知识,再从操作系统层面看SqlServer的内存分配。
一、 Windows常用内存术语
1. Virtual Address Space(虚拟地址空间)
应用程序能申请访问的最大地址空间。
在32位服务器上,由于地址总线长度是32位,服务器最大寻址空间为2^32B (4G);而64位服务最大寻址空间高达2^64B(8TB)。对于现有应用来说,这个大小相当于是无限的(当然再过几年就难说了)。
注意虚拟地址空间存放的数据信息不一定都在物理内存中,可能会放在缓存文件中(Paging file)。
2. Physical Memory(物理内存)
内存芯片提供的物理存储空间。要频繁访问的数据对象必须能长时间地缓存在物理内存中,才能达到最优的效率。
3. Reserved Memory(保留内存)
应用程序可以通过调用一些Windows API提前申请保留一块内存以供将来使用。如果其他程序访问到保留内存,会报错内存越界。注意保留内存只是虚拟地址空间的一段地址,而不是真正物理内存空间。
4. Committed Memory(提交内存)
将预先保留的内存页面正式提交使用,提交的页面在访问时最终转换到物理内存中存储。
5. Shared Memory(共享内存)
windows提供了在进程和操作系统间共享内存的机制,共享内存可理解为对一个以上进程可见的内存、或存在于多个进程的虚拟地址空间。
6. Private Bytes
某个进程提交的地址空间中非共享的部分。
7. Working Set
进程提交的内存中存放在物理内存的部分。
8. Page Fault(页面访问错误)
分为Soft/Hard ,访问一个存在虚拟地址空间,但不存在于当前进程working set中的页面时,就会发生Page Fault。Windows内存管理组件会处理每个Page Fault,首先判断是否是访问越界导致的。如果不是,会有两种情况:
目标页面在硬盘中,这种访问会产生硬盘读写,称为Hard Fault。目标页面在物理内存中,但没有直接放在这个进程的working set下,需要windows重定向。此时不会导致硬盘操作,称为soft fault,一般soft带来的性能影响可以忽略。
9. System Working Set
Windows系统自身也需要使用物理内存,也有Working set。
System Working Set包括:system cache、paged pool、non paged pool、system mapped views
可以通过性能监视器里的memory:cache bytes监控整体使用情况,使用Memory:cache faults/sec监控发生在系统内存上的page fault。
10. System Cache(系统高速缓存)
用于映射在系统高速缓存中打开的文件页面,提高磁盘I/O速度,性能监视器Memory:cache resident bytes可以监控。
11. Non Paged Pool (非页交换区)
包含一定范围内的系统虚拟地址的内存交换区,可以保证在任何时候都驻留在物理内存中,在系统初始化时创建。可以通过Memory:pool Nonpaged Bytes监控。
这块缓存可以被所有进程共享,最常见的用途是存放所有对象的指针(Object Handles)
12. Paged pool(页交换区)
系统空间中可以调入或调出系统进程工作集(Working set)的虚拟内存区域,在系统初始化时创建。可通过Memory:pool Paged Bytes和Memory:pool paged resident bytes监控。
13. Stack(栈)
每个线程有两个栈,一个内核模式(kernel mode),一个用户模式(user mode)。每个栈是一块内存空间,存放线程运行的过程或函数的调用地址,以及所有参数的值。
14. In Process
运行在同一个进程的地址空间里。优点是速度快,无需上下文切换;缺点是管理更复杂,如果dll在内存使用上管理不善,将出现严重错误、影响进程安全性。
15. Out of Process
运行在不同的进程地址空间里。
16. Memory Leak(内存泄漏)
一直不断地保留和提交内存资源,哪怕它们已不再使用,也不释放给其他用户重用。
SqlServer的内存泄漏分为两种:
一种是sql server作为一个进程,不断地向windows申请内存资源,直到整个windows内存耗尽(现在已经非常少见)另一种是sql server内部某个组件不断地申请内存,直到把能申请到的内存耗尽,使得其他组件不能正常运行。
二、 32位下Windows的地址空间及AWE
1. 核心态与用户态
默认情况下,windows进程有4G虚拟地址空间,其中2G给内核模式(kernel mode),剩下的2G给用户模式(user mode),这两部分严格区分,不会因为一部分用尽就给划分另一部分的内存。
SqlServer绝大部分命令运行在用户态,因此其最大可用内存只有2G,对现在而言,这个值实在是太小。
2. AWE
当时为了解决这个问题,有一种被称作AWE(Address Windowsing Extensions,地址空间扩展)的技术广泛使用。这种技术允许为32位应用程序分配64G物理内存。
SqlServer 2005及2008支持该技术(2012开始不再支持),开启只需用sp_configure命令将“AWE Enabled”打开,重启SqlServer服务即可。
开启此功能需要SqlServer启动账号有Windows上的lock pages in memory权限SqlServer中不是所有内存申请都会调用AWE技术,也不是所有内存请求都能使用扩展内存因此,AWE并不能彻底解决该问题。随着64位服务器的出现,这个问题才得到了很好的解决。64位应用程序虚拟地址空间可达8T,对目前来说,相当于无限。
三、 Windows上的内存使用检查
对于Windows系统来讲,主要从下面这三个角度分析内存的使用。
1. Windows系统使用情况
整体使用分析(性能监视器)
committed bytes:整个Windows系统使用的内存总数,包括物理内存和文件缓存中的数据commit limit:整个Windows系统能申请的最大内存数,其值等于物理内存+文件缓存大小Available MBytes:系统空闲物理内存数,直接反应windows是否有内存压力page file%usage和page file%peak usage:反应缓存文件使用量,使用量越大说明物理内存与实际需求差距越大pages/sec:hard page fault 每秒从磁盘读/写的页面数,如果过于频繁,说明内存可能不足
Windows自身内存使用情况
memory:cache bytes:系统working set(使用内存数)memory:system cache resident bytes(system cache):系统高速缓存消耗的物理内存memory:pool paged resident bytes:页交换区消耗的物理内存memory:system driver resident bytes:可调页的设备驱动程序代码消耗的物理内存memory:system code resident bytes:ntoskrnl.exe中可调页代码消耗的物理内存
system pool
如前文所述,Windows中有两块重要的交换区(pool),如果出现内存泄漏或空间用尽,对系统影响很大,也需检查。
2. 单个process使用情况
如果Windows可用内存已经不足,而大部分又非Windows系统占用,就要单独分析各个process,看哪个进程占用最多。性能监视器中有很多process:开头的监控可以用于分析,名字和含义跟前面类似,不一一列出了。
检查主要是为找到:
使用内存最多的进程内存使用量不断增长的进程故障时间段内存突变的进程
四、 内存使用与其他系统资源的关系
如果内存有瓶颈,一般cpu user time不会很高而cpu system time会高,因为系统要大量做paging操作,所带来的磁盘IO操作必须运行在system下。此时cpu使用率不会为0,但一般也不会超过50%。
分析服务器内存时需要注意以下几点:
首先确认服务器和SqlServer分别是32位还是64位的观察监控时必须结合各监控值间趋势和相互关系,不要仅用一两个值就下结论性能调优建议从内存开始检查,这往往是对数据库影响最大的一项别忘记检查windows系统自己的内存使用检查其他应用检查的内存使用(参考上一节)分析内存对CPU和IO的影响
五、 SqlServer内存使用与Windows间的关系
默认情况下,建议SqlServer动态使用内存,它会定期查询系统以确定可用内存量。SqlServer使用内存通知API QueryMemoryResourceNotification 确定缓冲池何时可以继续分配内存。当Windows内存不足时,SqlServer也可以通过该API知道,决定何时释放内存。
sqlserver动态使用内存是如何实现的?
SqlServer有两个重要的内存计数器:Total Server Memory和Target Server Memory。
Total Server Memory:SqlServer自己分配的buffer pool内存总和Target Server Memory:SqlServer理论上能使用的最大内存数,min(AWE,"Max Server Memory",当前服务器可用内存数)实现原理其实很简单,就是比大小:
Total Server Memory < Target Server Memory:SqlServer知道系统还有足够内存,当需要缓存新数据时,会分配新的内存地址空间Total Server Memory = Target Server Memory:SqlServer知道已经用完了能给它的内存,当需要缓存新数据时会清理自己的现有内存空间,给新的内存使用Total Server Memory > Target Server Memory:如果sqlserver收到Windows内存压力信号,会调小 Target Server Memory的值,使得Total Server Memory > Target Server Memory。此时SqlServer开始内存清理动作,调小自己的地址空间,释放内存,这个过程很有可能影响数据库性能。
最后注意一下,Total Server Memory、Target Server Memory指的都是逻辑上的内存大小,而非物理空间大小。不过在大部分情况下,可以认为Total Server Memory和实际物理内存使用量相差不大。
六、 SqlServer内存使用量突降现象
如果你在SqlServer错误日志中看到了以下报错,很大可能SqlServer性能会受到严重影响
spid1s a singnificant part of sqlserver process memory has been paged out.
this may result in a performance degradation(性能降级)
duration:0 seconds
working set:1086400 commited:2160928 memory utilization:50%
常见原因如下:
windows突然申请了过多内核态内存,反过来压缩了用户态可用的物理内存某些硬件驱动程序突然申请了过多内核态内存,占用过多物理内存某些应用突然成功申请了大量物理内存,使得Windows内存非常紧张避免方法参考下节
七、 如何合理配置SqlServer内存
Windows和其他关键应用程序要预留足够内存在满足第一条的情况下,给SqlServer足够的内存安装64位操作系统,如果一定要用32位,务必打开AWE尽量让SqlServer独占服务器建议限制Max Server Memory参数建议设置Lock page in memory“Set working set size”已不能在Windows上固定SqlServer物理内存,请不要再使用