一些内存使用错误理解

开篇小感悟

  在实际的场景中会遇到各类奇怪的问题,为何会感受到奇怪,由于没有理论支撑的东西才感受到奇怪,SQL Server本身管理内存,咱们能够干预的方式也不多,因此平常很难遇处处理内存问题的案例。当遇到了原有的知识储备已经变得模糊,这是已经记不住第几遍阅读《SQL 2012实施与管理实战指南》内存管理章节,也分享给群友。数据库

一些内存使用错误理解

    本文来澄清一些用户常常对SQL Server内存使用的误解。对这些知识的理解能够帮助数据库管理员理解SQL Server的行为 
     1. Windows上还有不少物理内存没有被使用,就意味着SQL Server不缺内存
    这个观点是很是错误的,由于:
    (1)SQL Server极可能设置了Max Server Memory,约束了SQL Server继续申请内存的能力。( 注:实际场景中就遇到过客户128GB内存的机器SQL Server 的Max Server Memory 被设置成2048MB 致使严重的问题
    (2)在32位的机器上 ,因为虚拟地址空间的限制,SQL Server可能已经没法继续申请内存。
    例如,在一台4 GB或更大的32位服务器上,SQL Server最多只能使用2 GB物理内存。通常Windows会使用500 MB左右的物理内存,这台机器可能就有1 GB多的空闲物理内存。这部份内存是SQL Server不开AWE就用不到的。 因此,服务器上有不少空闲物理内存,只能说明Windows不缺内存,不能说明SQL Server本身不缺内存。( 这也是为何建议更换老一代服务器,使用64位的操做系统和SQL Server的缘由
 
     2.  SQL Server进程的Private Bytes(或Working Set)在不停地向上涨,说明SQL Server有内存泄漏的问题
    偏偏相反,对于申请内存,SQL Server有严格的限制。在32位的服务器上,不论是Buffer Pool仍是MemToLeave,都有一个使用最大上限。当Windows感受到有内存压力的时候,SQL Server又会主动地释放内存因此做为一个进程,SQL Serve发生内存泄漏的机会是很是小的。
    之因此会有这样的疑惑,是由于SQL Server启动的时候,仅会Commit它启动所须要的那部份内存。随着用户的使用,SQL Server会不断地申请内存,直到Windows感受到内存压力,或者SQL到了本身的上限为止,在这以前,SQL Server的内存使用量的确会不断地增长。对SQL Server来说,缓存越多的数据,它的性能会越好这种增加是正常的,不用焦虑若是不但愿SQL Server使用那么多内存,只需设置Max Server Memory这个上限便可。
  ( 注: 实际状况中不少人提到过,SQL Server居然吃掉了全部服务器的内存,是否是内存泄露了?或问内存是否是这就是我系统的瓶颈呀?) 
 
    3.  Max Server Memory的值,就是SQL Server内存使用量的最大值。超过这个值就不正常
  Max Server Memory这个值应该是Buffer Pool的上限(此点针对SQL Server 2005/2008而言,对于SQL Server 2012内存管理发生了很是大的变化),而不是SQL Server全部内存使用的上限。因为SQL Server 内存的使用包括Buffer Pool和MemToLeave,因此SQL Server实际内存使用量必定会比Max Server Memory要大可是在正常状况下SQL Server MemToLeave的使用会远小于Buffer Pool的使用,控制好Buffer Pool,就基木控制住了SQL Server的总体内存使用量
   ( 注: 建议不管内存是否存在压力都要合理的设置最大内存,PS:我也曾经被使用的内存超过设置的Max Server Memory吓了一跳
  
     4. SQL Server的内存使用总量,就是性能监视器里面的SQL Server:Memory Manager一Total Server Memory的值
    性能监视器里面与SQL Server相关的counter,都是SQL Server本身负责收集的。从SQL Server 2005之后,SQL整合了全部的内存申请,让它们使用同一的接口。因此SQL Server对本身申请的内存数量,是了如指掌的,但问题是,在SQL Server进程里运行的代码不都是SQL Server本身的代码。对第三方的代码,SQL Server是不知道它们申请了多少内存的。
    SQLServer:Memory Manager - Total Server Memory的值,是SQL Server本身的代码申请的内存空间大小。真正SQL Server进程申请的空间值,会比这个值大一些。(具体大多少和MemToLeave的大小有关系)
    若是SQL Server没有开启AWE,SQL Server进程申请的逻辑内存数和物理内存数能够由Process下的Private Bytes和Working Set看出。这两个值会包含全部的内存支出,包括SQL本身的代码和第三方的代码。
    若是SQL Server开启了AWE,问题就比较尴尬了。由于Windows没有办法正确判断出一个使用了AWE 内存的进程,究竟总共用了多少内存。咱们只能借助SQLServer:Memory Manager一Total Server Memory来判断SQL Server的Buffer Pool使用量。至于SQL Server本身申请的内存总数(Buffer Pool + MemToLeave ),能够经过查询和内存相关的DMV计算出来,但第三方的代码申请的内存,就很难作精确计算了
   
  
     5.当系统有内存压力的时候,SQL Server老是会自动释放内存
    默认状况下,SQL Server的确会在系统有内存压力的时候自动释放内存可是有个例外:SQL Server启动时会试图作“Lock Page In Memory”的动做。若是启动帐号有这个权限,动做就会成功。那么当同一台服务器上的其余应用程序须要内存的时候,SQL Server极可能不会释放内存。因此在这种状况下,建议SQL Server设置Max Server Memory上限。
  ( 注: Lock Page In Memory不少资料上写到SQL的内存不会被释放了,但实际状况中,当操做系统感受到压力同样会把SQL的内存释放掉,也是错误理解6的由来) 
 
     6.  SQL Server有办法将本身的内存绑定在物理内存里
    SQL Server的确想经过Lock Page In Memory的方法达到这个目的。可是,做为一个用户态为主的应用程序,它仍是会受限于核心态。若是核心态里发出内存要求,SQL Server就会被迫把本身的内存释放出来。
 
     7.增长MemToLeave的大小能够提升SQL Server的性能
    在32位的SQL Server上,默认MemToLeave是256 MB+0.5 MB x ( Max Thread数目)。若是MemToLeave 用完了,SQL Server的一些重要功能就不能进行,甚至新的链接都创建不起来因此一些对MemToLeave需求比较大的SQL Server,例如,一些常常运行Linked Server分布式查询的SQL Server,或者是一些运行CLR,Extended Stored Procedur的SQL Server,可能不得再也不加一些MemToLeave空间。这可使用SQL Server的
一个启动参数一g完成。例如,若是想把MemToLeave设成512 MB+0.5 MB x ( Max Thread数目),能够加启动参数一g512。
    可是须要想清楚的是,SQL Server的虚拟地址空间只有2 GB,给MemToLeave越多,Buffer Pool能拿到的 就越少。Data Cache的内存还能够从AWE扩展的内存补,Buffer Pool里的Stolen内存就没办法了。因此其实 这是拆东墙补西墙,关键要看哪一块内存对SQL Server的性能和稳定运行最重要。没必要要多给,这会浪费资源, 影响Buffer Pool里面的性能。只有肯定了SQL Server的MemToLeave的确不够,才应该去增大它
  
  8.增长物理内存必定会提升SQL Server的性能
    既然SQL Server这么喜欢内存,那管理员多给服务器配备一些内存,是否是就必定可以提升性能呢?不少时候这个想法是对的,可是并非老是正确。这是由于增长的内存SQL Server不必定用获得。
    (1)首先要检查是哪一部分的内存有瓶颈,是Database Cache,仍是Stolen,是Buffer Pool,仍是MemToLeave。
    (2)要检查缺的那部份内存是否是已经到了理论上的上限,新加内存SQL Server用不用得上例如,在32位+AWE的服务器上,Buffer Pool里的Stolen Memory最多也不过1.6 GB。若是是这一部份内存不够,再加内存也没有用。只有将系统升级到64位,才能突破这些限制。
    (3)加人的内存,通常大部分都会被Buffer Pool使用,这样SQL Server就会缓存更多的数据页面和执行计划,大多数时候这会对性能有帮助。若是Database Pages没有压力,SQL Server会缓存太多的动态T-SQL执行计划,对性能没什么好处,反而会增长SQL Server的维护成本。只有在SQL Server的Database Page缺内存的时候,增长内存才会对性能有明显帮助。若是数据库比较小,经常使用数据页面已经缓存在了内存里,增长内存对性能不会有太大帮助。
  ( 注: 内存这个东西对于一些初级DBA分析起来仍是有些难度,而不少状况下只要看到内存压力就要添加内存这样也是不对的,不少时候内存的消耗很本身程序的语句优化程度也有着很是大的关系) 
 
  9. Stolen的内存真的是偷来的吗
   不少在描述Stolen的内存块的时候都说这块内存是不须要保留(Reserve)而直接提交(Commit )使用的,因此这块内存叫做Stolen。这么说错了吗?其实,从Windows的层面,对于任何内存的使用,都必须遵循先Reserve再Commit的过程。对于一块内存,若是不Reserve而直接使用会致使访问违例(Access Violation)由于SQL Server内部的内存管理机制,全部要使用的内存,Buffer Pool都已经帮咱们保留(Reserve)好了若是SQL所要作的,是用Buffer Pool已经保留(Reserve)好了的那部分地址空间去直接提交(Commit ),并且,这一部份内存又不是用来存放Buffer的,就被称为Stolen

--------------博客地址---------------------------------------------------------------------------------------缓存

博客园原文地址: http://www.cnblogs.com/double-K/服务器

 

 欢迎转载,请保留出处。分布式

-----------------------------------------------------------------------------------------------------性能

 

  总结 : 本文介绍了一些常见的内存方面的误区,都是文字描述,可能不少人没法真正的理解,但当遇到过这样的场景或奇怪的问题发生时,回头看看也会加深一下感觉的!
优化

  PS:我也是当遇到真正场景时才能明白,理论知识也是须要不断熟悉、不断理解的。spa

 

 ----------------------------------------------------------------------------------------------------操作系统

注:此文章为原创,欢迎转载,请在文章页面明显位置给出此文连接!
若您以为这篇文章还不错请点击下右下角的推荐,很是感谢!blog

相关文章
相关标签/搜索