SqlServer 内存篇(二)—— SqlServer内存管理模式及常见问题

以下概念按sqlserver 2005及2008中描述,2012中有改变,参考系列最后一篇。

 

一、 SqlServer内存参数

与其他数据库相比,sqlserver可调整的内存参数很少,只有以下几个:

SqlServer 内存篇(二)—— SqlServer内存管理模式及常见问题_第1张图片

 

1. Min Server Memory(MB)

定义sqlserver最小buffer pool值。

注意以下两点:

  • Min Server Memory是一个逻辑概念,控制sqlserver total server memory大小。数据是放在物理内存还是缓冲文件由windows决定,因此这个值不能保证sqlserver最小物理内存数
  • Min Server Memory指的是,在sqlserver地址空间增长到该大小后就不会再小于这个值。sqlserver在刚启动时只会commit需要的内存,此时内存量小于Min Server Memory很正常。

 

2. Min Server Memory(MB)

定义sqlserver最大buffer pool值。

也注意以下两点:

  • Max Server Memory也是一个逻辑概念,控制sqlserver total server memory大小。
  • Max Server Memory只能控制sqlserver buffer pool部分内存最大值,这不是sqlserver内存的全部,所以sqlserver使用量大于这个值很正常(但不应大太多)

一般而言,SqlServer发生内存泄漏可能性很小。如果是刚启动的SqlServer,占用内存会逐步增大至max server memory (MB)参数设置的最大值(修改不需重启)而后渐趋平稳。如果未设置该参数,Windows默认是2048TB,相当于无限制;Linux默认是操作系统内存的80%,留20%是为避免被OOM。

 

3. AWE Enabled

启用AWE以突破32位服务器2G用户寻址,sqlserver 2012开始已不支持。

 

4. Lock pages in memory

企业版自动开启,可以在一定程度上确保sqlserver物理内存数,当然如果windows内存压力太大,开启也救不了。

 

二、 sqlserver内存分类

 

1. 按用途分类

1)database cache:缓冲池,类似oracle buffer cache,通常是最大的区域

2)各类consumer:sqlserver功能组件统称为consumer,主要包含:

  • connection:存储连接信息,另外还包括输入/出缓冲池
  • general:存储锁数据结构、表和索引元数据等
  • query plan:存储语句和存储过程执行计划,这块区域也比较大
  • Optimizer:sqlserver在生成执行计划过程中消耗的内存
  • utilities:bcp、log manager、并行查询、备份等特殊操作所需内存

3)线程内存:sqlserver为进程内的每个线程分配0.5M内存,存放线程数据结构及相关信息

4)第三方代码:由于它们不是sqlserver自身代码,所以sqlserver也不知道它们申请了多少内存。一般这块内存不会很大,除非第三方代码存在大量内存申请甚至内存泄漏,或者linked server需要从远端数据库取大量数据。

 

2. 按申请方式分类

1)先reserve再commit:database cache使用的申请方式

2)直接commit(称为stolen):database cache之外其他部分内存使用的申请方式

之所以区分这两种申请方式,是因为sqlserver不会对stolen的内存使用AWE功能。也就是说,32位服务器AWE扩展的内存只能存放database cache数据,其他内存还是要在2G里想办法。

 

3. 按申请大小分类

1)single page allocation:对所有可以分成<=8KB为单位的内存申请,sqlserver分配一个页面(8KB)。这些页面集中在一个内存区域管理,这个内存区域称为buffer pool。

2)multiple page allocation:对>8KB为单位的申请,sqlserver将它们存在另一个区域,这个内存区域称为multi-page(以前叫MemToLeave)。

 

4. 各类内存分类方法间的关系

下面按用途分,看看各种类型使用多大内存,存放在什么区域。

1)database cache:都是数据页面,均以8KB为单位,放在buffer pool。

2)各类consumer:

  • connection:与network package size(客户端和sqlserver通信的每个数据包大小)有关。若是默认的4K,输入/出缓存会放在buffer pool;若为8K或更大,输入/出缓存放在multi-page
  • general:绝大部分内存以8K为单位申请,使用buffer pool;但若有语句特别长,需要使用大于8K为单位的内存,会放在multi-page
  • query plan、optimizer、utilities:与general类似,绝大部分使用buffer pool;但若有语句特别长,它的query plan、Optimizer等会使用一部分multi-page

3)线程内存:每个线程分配0.5M内存,自然放在multi-page

4)第三方代码:由于不是sqlserver自身代码,sqlserver也不知道它们申请了多少内存,所以都放在multi-page

SqlServer 内存篇(二)—— SqlServer内存管理模式及常见问题_第2张图片

 

三、 不同服务器下sqlserver各部分内存上限

 

1. 无AWE

SqlServer 内存篇(二)—— SqlServer内存管理模式及常见问题_第3张图片

 

2. 32位有AWE

SqlServer 内存篇(二)—— SqlServer内存管理模式及常见问题_第4张图片

 

四、 sqlserver内存相关常见问题

 

1. windows还有很多物理内存未使用,是不是sqlserver就一定不缺内存?

当然不一定,因为windows内存多不代表sqlserver就能用到:

  • sqlserver设置Max Server Memory参数会限制sqlserver继续申请内存
  • 使用32位服务器,未开启AWE时sqlserver最多只能用2G内存;就算开了,multi-page部分还是用不到

 

2. sqlserver进程内存使用量持续上涨说明sqlserver有内存泄漏?

也不一定。前面提到过,sqlserver在启动时只申请需要的内存,随着用户使用,sqlserver会继续申请内存直到windows有压力或者到达Max Server Memory参数上限,这种持续上涨是正常的。

作为一个成熟的软件,sqlserver本身发生内存泄漏的可能性很低,应用程序发生内存泄漏的可能性更高一点。

 

3. Max Server Memory代表sqlserver内存的最大值,超过就不正常?

这个也在前面提到过,Max Server Memory只能控制sqlserver buffer pool部分内存最大值,这不是sqlserver内存的全部,所以内存使用量大于这个值很正常(但不应大太多)。

 

4. 当系统有内存压力时,sqlserver一定会释放内存?

  • 如果未成功开启Lock page in memory,当系统有内存压力时,sqlserver会释放内存
  • 如果成功开启Lock page in memory,当系统有内存压力但不大时,sqlserver不会释放内存
  • 如果成功开启Lock page in memory,但是系统内存压力很大,sqlserver还是会释放内存

如果这类问题发生,对SqlServer影响会非常大。轻则SqlServer响应异常缓慢,重则大量用户无法连接SqlServer,SqlServer短暂hang死。错误日志中常常能看到如下告警:

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%

 

5. 增加multi-page可以提高sqlserver性能?

如果能确定是multi-page内存不足导致的问题,适当增加multi-page当然可以提高sqlserver性能

如果不是,加大了未必会有用。尤其在32位未开启AWE的服务器,sqlserver可用内存只有2G,加大multi-page就意味着要减小buffer pool,很有可能得不偿失。

 

6. 增加服务器内存一定能提高sqlserver性能?

  • 这跟第一个问题类似,sqlserver要用得到才有可能提高性能(用不到的情况不重复列了)
  • 如果数据库很小,现有内存已足够缓存常用数据,再加内存不会有什么帮助,甚至会缓存很多无用数据,加大维护成本
  • 如果sqlserver确实缺内存,也要先搞清楚是哪部分缺内存(方法下篇讨论)

 

7. stolen内存真的是偷来的吗?

其实从windows层面,任何内存都需要先reserve再commit。

为什么stolen部分可以直接commit?是因为在sqlserver中,buffer pool已经将所有将需要的内存提前reserve了。

如果sql要做的是用buffer pool已经reserve的地址空间去commit,而commit后的内存又不存放database cache数据,这部分内存就被称为stolen。

你可能感兴趣的:(sqlserver,性能)