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)引导语句运行) 本篇继续玩转模块 ...
随机推荐
- Sanarus Medical --国外一家研究乳腺癌治疗的科技公司
Sanarus Medical --国外一家研究乳腺癌治疗的科技公司 http://www.sanarus.com/
- 摘记 pyinstaller 使用自定义 spec
下面的是官网的文档, 我们可以用自定义spec的方式把想要的文件打包到目标文件夹里面 例如: 我们在程序中用了一个图标 test.ico, 如果我们只用 pyinstaller -w test.py ...
- 关于公司VPN专线接入的一个案例
最近互通网络技术部门收到一到封邮件,是关于公司VPN接入的问题,问题如下: 条件:A区为办公地点1,其他办公电脑20台,并通过写字楼的宽带接口联通外网. B区为新办公地点2,预设应用.数据库.备份服务 ...
- python day1 变量的命名和赋值
变量 一.变量的命名 1.不能以数字进行开头 2.不能包含特殊字符 3.不能是python内部的某些关键字 a = 123print(a)123 --------------------------- ...
- jQuery选择器引擎和Sizzle介绍
一.前言 Sizzle原来是jQuery里面的选择器引擎,后来逐渐独立出来,成为一个独立的模块,可以自由地引入到其他类库中.我曾经将其作为YUI3里面的一个module,用起来畅通无阻,没有任何障碍. ...
- iOS常用公共方法
iOS常用公共方法 字数2917 阅读3070 评论45 喜欢236 1. 获取磁盘总空间大小 //磁盘总空间 + (CGFloat)diskOfAllSizeMBytes{ CGFloat si ...
- (转)【推荐】初级.NET程序员,你必须知道的EF知识和经验
转自:http://www.cnblogs.com/zhaopei/p/5721789.html [推荐]初级.NET程序员,你必须知道的EF知识和经验 阅读目录 [本文已下咒.先顶后看,会涨 ...
- 【开发环境】JAVA 环境变量批处理
@echo off set regpath=HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environmen ...
- 手机移动端confirm替换方案
//弹框 ;(function () { var ConfirmBox = function (options){ this.defaults = { title:"", topT ...
- 十分钟能学会的框架,MVC+20个常用函数
LazyPHP(以下简称LP)是一个轻框架. 之所以开发这么一个框架,是因为其他框架给的太多.在高压力的情况下,ORM和盘根错节的对象树反而将简单的页面请求处理复杂化,在调试和性能上带来反面效果. L ...