SQL SERVER 内存学习系列(一)
最近帮客户解决发布订阅的问题时,突然遇到这样一个问题发布订阅中报下面的错误,另外执行alter table 操作时也会报错 :


问题很奇怪发布订阅和CLR有什么关系?memtoleave内存是个啥?回忆学习体系架构的时候,确实看到过memtoleave内存,但是是什么已经完全想不起来了,所以拿起书本回味一下学习的快感...
---------------转载请注明出处------------http://www.cnblogs.com/double-K/p/5049417.html--------------------
抛开问题我们先看一下SQL SERVER的内存结构:
1.从操作系统层面看SQL SERVER内存分配:windows 和SQL SERVER的关系就像君与臣一样,windows的统治下SQLSERVER和其他应用如notepad并无两样,当操作系统级别都内存紧张的时候SQL SERVER的内存一样会紧张。所以了解WINDOWS的内存结构同样重要。
- Virtual Address Space (虚拟地址空间)
- Physical Memory (物理内存)
- Reserved Memory (保留内存)
- committed Memory (提交内存)
- Shared Memory (共享内存)
- 等等好多种有兴趣的可以自己看一下
2.SQL SERVER内存的使用分类:
- 按用途:
- database cache :存放数据页面的缓冲区,SQL SERVER数据库里的数据都是以8KB为一个页面存储的,当有用户需要使用到这个页面的时候SQL SERVER就会把整个也都调入内存。所以8KB是数据访问的最小单元。
- 各类consumer :SQL SERVER各类组件,他们必须申请内存来支持他们完成工作,如:SQL SERVER需要为每一个连接分配一个数据结构,存储关于连接的信息,还会分配输入和输出的缓冲池(客户发送的指令/指令所获取的结果,等待客户端取走),语句的缓存计划等等。
- 线程内存 : SQL 会为进程内的每个线程分配0.5MB的内存,用以存放线程内的结构和相关信息。
- 第三方代码申请的内存 : 如CLR、LINKEDSEVER、COM等,这部分内存一般不会很大,但是假如一个linked server的分布式查询需要从远端取回大量的数据,那么这块内存就会使用的很大。所以这块内存的监视也不能忽视。
- 按申请方式 :
- 预先reserve 一块大内存,然后在使用的时候一小块一小块的commit
- 直接从地址空间申请commit,这种方式成为stolen。(AWE功能无效,扩展出来的内存只能用于database cache,其他还是需要在2GB里解决)
- 按申请大小 :
- 小于等于8KB (buffer pool)
- 大于8KB (multi-page 2008以前叫memtoleave)
- 按用途:
我们以按照大小的分类作为说明:申请小于等于8KB 这些页面都集中管理,这块内存称为 buffer pool,另一部分申请大于8KB的称为multi-page(memtoleave),memtoleave这块区域的内存分配很大一部分不受SQLSERVER本身控制,或者可以说只在SQL SERVER内部分配,但是却是由加载在SQL SERVER内部的其他DLL来分配的,如CLR。
32位的年代启动时需要保留我们配置需要的memtoleave大小(包含worker thread所需)的地址空间,然后把其他的都给buffer pool。
64位时代以后由于地址空间可以理解为无限大,所以SQL SERVER不再控制memtoleave这段空间的大小,甚至已经可以抢夺database cache了。
以一个表格总结一下:
| 类型 | database cache | consumer | 第三方代码 | threads |
| reserved/commit | 是 | 一般不是 | 一般不是 | 不是 |
| stolen | 不是 | 是 | 是 | 是 |
| buffer pool | 所有 | 绝大部分 | 没有 | 没有 |
| memtoleave | 没有 | 一小部分 | 所有 | 所有 |
---------------转载请注明出处------------http://www.cnblogs.com/double-K/p/5049417.html--------------------
简单的说明了一下SQL 的内存,有几点需要注意的也简单提一下:
1.WINDOWS不缺内存SQL 就不会缺内存吧?
答:这个是很错误的(1)如果是32位,由于虚拟地址空间的限制SQL 可能无法继续申请内存。有人会说我可以开AWE,前文也提到过AWE不是万能的,有64位为什么还要选32位呢? 对吧。(2)SQL SERVER很可能设置了max server memory约束了SQL 继续申请内存的能力,这个真遇到过,256G内存的服务器 max server memory 被设置成了2个G。
2.我们设置SQL 的最大内存 为20G,为什么有的时候观察sql进程的内存使用会超过20G?是不是这个没用呢?
答:属性->内存->最大内存 (max server memory)设置的其实buffer pool的最大值,里面没有包含memtoleave这段空间的大小,所以有的时候会看到SQL 使用的内存超过了设置的max server memory
- 3.我这是一台SQL SERVER专用服务器所以不需要设置max server memory,内存都给SQL SERVER。
- 答:这个问题是好多用户遇到的问题,看似没有问题,但是忽略了一点 SQL SERVER是一个很喜欢内存的应用所以很可能吃掉大量内存导致windows系统没有足够内存使用,那么这时候君臣关系就体现的淋漓尽致了,君(windows) 要臣死(释放内存)臣不得不死呀...这个释放在一定程度上可不是单单让windows够用了,很可能导致SQL内存陡降,以致SQL 短时间假死(操作无响应),一般我比较推荐操作系统20% ,SQL SERVER 80%如果服务器还有其他应用还要在SQL 中减掉应用所占的内存。
---------------转载请注明出处------------http://www.cnblogs.com/double-K/p/5049417.html--------------------
说了这么多回到我开篇的问题上,为什么出现这个情况memtoleave内存不足呢?看完文章也许你已经有了答案。
我说一下我排查问题的步骤,当客户发给我报错截图的时候我第一反应必须是了解客户的环境,因为不能远程所以我询问了操作系统版本SQL 版本,补丁及内存设置等等...告诉我64位的WINDOWS SERVER2008 ,SQL SERVER2008R2,遗憾的是当时客户没有select @@version确认SQL 版本,我也理所当然的认为装的肯定是64位SQL SERVER呀!!经过翻阅资料网上寻找答案始终想不明白为什么会出现这个显现...最后再次要求客户确认SQL 版本时才发现64位操作系统竟然误安装32位SQL SERVER 这下问题瞬间明了。
这个32位memtoleave的内存初始是多大呢?256M + 256(个thread) X 0.5MB = 384MB,可以通过修改启动参数 + -g 1024 (分配1024MB)解决这个问题,但是这个问题的根本不是修改启动参数,这仅仅是表名现象,最终的操作必然是重新安装SQL SERVER x64 !!!当然这会对用户的应用造成很大的影响。
---------------转载请注明出处------------http://www.cnblogs.com/double-K/p/5049417.html--------------------
以为这个案例我突然发现自己的体系结构如此之脆弱...遇到问题虽然见过却没有完善的知识体系来支撑,所以准备再次学习一下SQL 内存篇!!同时也会奉上后续学习文章!!
哦了~~~
SQL SERVER 内存学习系列(一)的更多相关文章
- SQL SERVER 内存学习系列(二)-DMV查看内存信息
内存管理在SQL Server中有一个三级结构.底部是内存节点,这是最低级的分配器,用于SQL Server的内存.第二个层次是由内存Clerk组成,这是用来访问内存节点和缓存存储,缓存存储则用于缓存 ...
- SQL SERVER 内存学习系列
http://www.cnblogs.com/double-K/p/5049417.html http://blog.sina.com.cn/s/blog_5deb2f5301014wti.html ...
- SQL Server调优系列基础篇(并行运算总结)
前言 上三篇文章我们介绍了查看查询计划的方式,以及一些常用的连接运算符.联合运算符的优化技巧. 本篇我们分析SQL Server的并行运算,作为多核计算机盛行的今天,SQL Server也会适时调整自 ...
- SQL Server调优系列基础篇(并行运算总结篇二)
前言 上一篇文章我们介绍了查看查询计划的并行运行方式. 本篇我们接着分析SQL Server的并行运算. 闲言少叙,直接进入本篇的正题. 技术准备 同前几篇一样,基于SQL Server2008R2版 ...
- SQL Server调优系列基础篇(索引运算总结)
前言 上几篇文章我们介绍了如何查看查询计划.常用运算符的介绍.并行运算的方式,有兴趣的可以点击查看. 本篇将分析在SQL Server中,如何利用先有索引项进行查询性能优化,通过了解这些索引项的应用方 ...
- SQL Server调优系列基础篇(子查询运算总结)
前言 前面我们的几篇文章介绍了一系列关于运算符的介绍,以及各个运算符的优化方式和技巧.其中涵盖:查看执行计划的方式.几种数据集常用的连接方式.联合运算符方式.并行运算符等一系列的我们常见的运算符.有兴 ...
- SQL Server调优系列进阶篇(查询语句运行几个指标值监测)
前言 上一篇我们分析了查询优化器的工作方式,其中包括:查询优化器的详细运行步骤.筛选条件分析.索引项优化等信息. 本篇我们分析在我们运行的过程中几个关键指标值的检测. 通过这些指标值来分析语句的运行问 ...
- SQL Server调优系列玩转篇(如何利用查询提示(Hint)引导语句运行)
前言 前面几篇我们分析了关于SQL Server关于性能调优的一系列内容,我把它分为两个模块. 第一个模块注重基础内容的掌握,共分7篇文章完成,内容涵盖一系列基础运算算法,详细分析了如何查看执行计划. ...
- SQL Server调优系列玩转篇二(如何利用汇聚联合提示(Hint)引导语句运行)
前言 上一篇我们分析了查询Hint的用法,作为调优系列的最后一个玩转模块的第一篇.有兴趣的可以点击查看:SQL Server调优系列玩转篇(如何利用查询提示(Hint)引导语句运行) 本篇继续玩转模块 ...
随机推荐
- My安卓知识2--使用listview绑定sqlite中的数据
我想在我的安卓项目中实现一个这样的功能,读取sqlite数据库中的数据并显示到某个页面的listview控件中. 首先,我建立了一个Service类,来实现对数据库的各种操作,然后在这个类中添加对数据 ...
- python smtplib发送邮件遇到的认证问题
python的smtplib模块主要是用来发送邮件的,使用起来比较方便. 使用程序发送邮件只需要写以下几行代码就OK了: #!/usr/bin/env python import smtplib s ...
- 深入浅出: Java回调机制(异步)
一.什么是回调 回调,回调.要先有调用,才有调用者和被调用者之间的回调.所以在百度百科中是这样的: 软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用.回调和异步调用. 回调 ...
- net软件自动生成开发编程框架编程机器人
有一个.net自动生成平台(编程机器人)推荐给大家,常规几天十几天的工作,机器人几分钟搞定,不写一行代码,留下大把休闲时光,适应于聪明人:不想太累的程序员(看看风景泡泡妞),不想多请人的老板(有限资金 ...
- 如何使cookie全站都生效?
一个页面设置的cookie, 默认在其同级目录下,及子目录下可以读取. 如果想让cookie整站有效,可以在根目录下setcookie 也可以用第4个参数,来指定cookie生效路径 setcooki ...
- javascript设计模式(单体模式)
主要内容: js中最基本.应用最广的模式就是单体模式,实现原理是将代码组织为一个逻辑单元,这个逻辑单元中的代码可以通过单一的变更进行访问,确保对象只存在一份实例. 单体模式的特点: 在网页中使用全局变 ...
- 为什么Smalltalk不流行
最近读到一本书,说Python程序员比Java程序员聪明.同理,懂Smalltalk的程序员也比Java程序员聪明.所以,我在StackOverflow上找到这个关闭很久的问题,整理了一下,跟大家分享 ...
- C、C++、Java、go的语法区别
详细C++.Java比较:http://www.cnblogs.com/stephen-liu74/archive/2011/07/27/2118660.html 一.C.C++的区别 在很大程度上, ...
- java-关于浏览器的判断
一.判断是手机还是电脑浏览器 public final static String[] agent = { "Android", "iPhone", " ...
- 判断Window在哪个屏幕
最近在做窗口最大化时需要一个功能,如果是多个显示器的话,需要在当前显示器最大化,由于是根据屏幕长宽进行设置Window大小,没有使用WindowState.Maximized,window.Left不 ...