[SQL Server]内存泄露(memory leak)——游标导致的内存问题 比眉伴天荒 2022-06-05 10:05 184阅读 0赞 转自:[http://blogs.msdn.com/b/apgcdsd/archive/2011/07/01/sql-server-memory-leak.aspx][http_blogs.msdn.com_b_apgcdsd_archive_2011_07_01_sql-server-memory-leak.aspx] 问题描述:客户反映SQL Server运行一段时间就会报出内存不足的错误,怀疑是有内存泄露。从SQL Server的error log里面看如下错误信息: 2009-05-14 10:54:20.71 server Error: 17803, Severity: 20, State: 17 2009-05-14 10:54:20.71 server Insufficient memory available.. 对于这种内存错误首先我们应该检查当前SQL Server的内存配置: 1. 32位的SQL Server还是64位的SQL Server? 2. 如果是32位的SQL Server,有没有启用AWE的选项。 3. 是否有设置最大服务器内存? 讲解这个问题之前需要先介绍一下32位和64位SQL Server在内存使用上的不同: 32位的应用程序在32位系统上的内存寻址空间是2GB的。我们可以使用AWE的方式使SQL Server使用超过2GB的物理内存,但是,寻址空间依然是2GB。 通过AWE扩展出来的内存,只可以用来作为数据缓冲区使用。除了数据缓存,SQL Server还需要使用内存来存储所有的执行计划,锁资源,用户连接信息,优化器使用作为评估语句执行计划的内存,语句执行内存等等。这些部分加起来不能超过2GB的内存。因此,即使我们为32位的SQL Server扩展了内存,一旦这2GB的内存不够提供给除了数据缓存的其他部分使用,SQL Server依然有面对内存不足的问题。本文中讨论的内存问题就是如此。 这里提供一篇文档,具体说明了如何为32位的SQL Server扩展内存:[http://support.microsoft.com/default.aspx?scid=kb;en-us;274750][http_support.microsoft.com_default.aspx_scid_kb_en-us_274750] **一旦我们使用了AWE选项为SQL Server扩展内存,我们一定要在sp\_configure里面设置max server memory,以保证OS可以保留足够的物理内存。** 我们回到这个内存的错误,检查系统的内存配置:该系统是32位的SQL Server 2000,启用了AWE选项,最大服务器内存设置为7500MB。这样我们有个初步的推断,问题可能是由于2GB限制以下的某个部分内存使用过多导致的。 接下来我们介绍另一个很重要的命令,这个命令在我们处理内存问题时经常会使用: DBCC memorystatus 这个命令是用来输出当前SQL Server的内存使用情况的。在SQL Server 2005以后,我们引入了一个新的DMV,其中包含了更详细的内存分配信息:sys.dm\_os\_memory\_clerks 在这个问题中,由于系统是SQL Server 2000,所以我们使用dbcc memorystatus来查看SQL Server的内存情况。这里有两篇文章分别介绍了SQL 2000和SQL 2005中如何查看dbcc memorystatus的结果: [http://support.microsoft.com/default.aspx?scid=kb;en-us;271624][http_support.microsoft.com_default.aspx_scid_kb_en-us_271624] [http://support.microsoft.com/default.aspx?scid=kb;en-us;907877][http_support.microsoft.com_default.aspx_scid_kb_en-us_907877] 我们进一步检查SQL Server 的error log: 2009-05-06 16:20:22.38 spid215 BPool::Map: no remappable address found. 2009-05-06 16:20:22.46 spid241 BPool::Map: no remappable address found. 2009-05-06 16:20:22.50 spid8 BPool::Map: no remappable address found. 2009-05-06 16:20:22.52 spid242 Buffer Distribution: Stolen=190614 Free=196 Procedures=271 Inram=0 Dirty=104759 Kept=0 I/O=0, Latched=35, Other=664125 2009-05-06 16:20:22.52 spid242 Buffer Counts: Commited=960000 Target=960000 Hashed=768919 InternalReservation=529 ExternalReservation=1426 Min Free=256 Visible= 191224 2009-05-06 16:20:22.52 spid242 Procedure Cache: TotalProcs=67 TotalPages=271 InUsePages=197 2009-05-06 16:20:22.52 spid242 Dynamic Memory Manager: Stolen=190767 OS Reserved=2584 OS Committed=2542 OS In Use=2538 Query Plan=156155 Optimizer=0 General=15253 Utilities=401 Connection=4046 2009-05-06 16:20:22.52 spid242 Global Memory Objects: Resource=9815 Locks=16467 SQLCache=76 Replication=2 LockBytes=2 ServerGlobal=28 Xact=5011 2009-05-06 16:20:22.52 spid242 Query Memory Manager: Grants=11 Waiting=15 Maximum=1512 Available=0 这里的输出结果就是DBCC memorystatus的一部分。Buffer Counts: Commited=960000 Target=960000 在这里的commited的值,是当前buffer pool的大小,target的值是计算出来的buffer pool的大小。如果target的值大于commited的值,说明buffer还要继续增长,反之,则是buffer pool要收缩。Hashed=768919这个是数据缓存的大小,即AWE扩展出来的这个部分。我们可以简单的计算一下,960000\*8k,刚好就是7500MB。其中数据缓存是6000MB左右。剩下的部分总共使用了1500MB。 接下来查看Dynamic memory manager的部分: **Stolen**. 是buffer pool中如下5个部分的总和(General, Query Plan, Optimizer, Utilities, Connection). 这个部分的内存分配页面都是小于8KB的。这里的stole的总和是190767,基本上等于960000-768919的差值。 这说明buffer pool中除去数据缓存的部分,剩下的内存就都是这5个部分���用了。 在stolen的部分中,我们看到Queryplan 的值非常高,156155\*8k=1219MB。Plan cache是用来缓存语句的执行计划的。在32位SQL Server有2GB的内存地址的限制情况下,单独的plan cache使用到了大于1200MB是非常惊人的了,这也是我们这个内存问题的根本原因。 接下来我们要研究为什么这个系统的plan cache会增长到1.2GB。通常情况下,SQL Server会定期的去清除长时间未使用的语句缓存,保证plan cache的部分不会涨得过大。我们同样也提供一个命令去手动的清除plan cache的内存:dbcc freeproccache 这个命令执行完以后,会将当前没有正在被语句使用的缓存的执行计划从SQL Server的内存中全部清除。我们在SQL Server上执行dbcc freeproccache命令后,再次使用dbcc memorystatus来检查queryplan的部分。在这套系统中,我们发现dbcc freeproccache并没有成功清除掉Queryplan的部分,这个部分依然显示超过1200MB。这就是为什么SQL Server也同样不同清除Queryplan,而导致Queryplan涨到超过1200MB的原因了。 前面我们讲过,dbcc freeproccache可以强制清除那些没有被语句正在使用的执行计划。如果不能清除,说明这些执行计划都在被使用中。那么什么情况会导致所有的执行计划都在被使用中呢?我们联想到问题的描述是这个内存的时候是慢慢增长上来的,那么这个情况就很有可能是应用程序中遗留了游标没有关闭。 检查系统中的活动游标,我们引入了另一个命令:DBCC ACTIVECURSORS 这个命令会将当前系统所有未关闭的游标打印出来: SPID Cursor Id Pages Stmt \--------------- ------------------------------------------------------------------ 55 180150581 2 select \* from MESSAGE\_DATA where MSG\_NUMBER = @P1 55 180150580 2 select mhead.msg\_number,customer\_id,originator,status,queue, 55 180150577 4 select macc.delivery\_time,macc.msg\_number,macc.recipient\_num 55 180150576 3 select mhis.msg\_number,mhis.recipient\_number,mhis.update\_tim 55 180150568 4 select mh.originator,mh.datatype\_id,mh.creation\_time,mh.reci 55 180150547 8 select mh.msg\_number,mh.orig\_msg\_number,mh.child\_msg\_number, 55 180150460 8 select customer\_id, company, contact\_name, contact\_phone, ma 62 180150847 10 select pii.msg\_number, pii.item\_number, pii.type, pii.amount 62 180150710 10 select pii.msg\_number, pii.item\_number, pii.type, pii.amount 62 180150661 10 select pii.msg\_number, pii.item\_number, pii.type, pii.amount ……. 这里输出了总共9600多个活动游标,并且同时输出了游标使用的语句。 到目前为止,问题就很清楚了。使用JDBC的应用程序遗漏了某些游标没有关系,因此导致这些游标使用的语句的执行计划一直无法被SQL Server清除。因此导致了QueryPlan占用了大量的内存,数据库报出内存不足的错误。 [http_blogs.msdn.com_b_apgcdsd_archive_2011_07_01_sql-server-memory-leak.aspx]: http://blogs.msdn.com/b/apgcdsd/archive/2011/07/01/sql-server-memory-leak.aspx [http_support.microsoft.com_default.aspx_scid_kb_en-us_274750]: http://support.microsoft.com/default.aspx?scid=kb;en-us;274750 [http_support.microsoft.com_default.aspx_scid_kb_en-us_271624]: http://support.microsoft.com/default.aspx?scid=kb;en-us;271624 [http_support.microsoft.com_default.aspx_scid_kb_en-us_907877]: http://support.microsoft.com/default.aspx?scid=kb;en-us;907877
相关 内存泄漏问题研究:Java对象引用导致的内存泄露案例 内存泄露在编程中是一个严重的问题,它会导致系统可用内存逐渐减少,影响程序性能甚至可能导致系统崩溃。下面我们将通过一个Java对象引用导致的内存泄露案例进行分析。 案例: `` 迷南。/ 2024年09月11日 23:54/ 0 赞/ 23 阅读
相关 python内存泄露memory leak排查记录 问题描述 A服务,是一个检测MGR集群主节点是否发生变化的服务,使用python语言实现的。 针对每个集群,主线程会创建一个子线程,并由子线程去检测。子线程会频繁... 红太狼/ 2024年04月18日 15:10/ 0 赞/ 40 阅读
相关 什么是内存溢出(Out Of Memory---OOM)和内存泄露 (Memory Leak) 1、内存溢出:(Out Of Memory—OOM) 系统已经不能再分配出你所需要的空间,比如系统现在只有1G的空间,但是你偏偏要2个G空间,这就叫内存溢出 例子:一 今天药忘吃喽~/ 2023年01月09日 12:33/ 0 赞/ 118 阅读
相关 什么是内存溢出(Out Of Memory---OOM)和内存泄露 (Memory Leak) 1、内存溢出:(Out Of Memory---OOM) 系统已经不能再分配出你所需要的空间,比如系统现在只有1G的空间,但是你偏偏要2个G空间,这就叫内存溢出 傷城~/ 2022年12月11日 12:23/ 0 赞/ 157 阅读
相关 使用Leak Canary检测应用的内存泄露 > > 欢迎Follow我的[GitHub][], 关注我的[简书][Link 1]. 其余参考[Android目录][Android]. [LeakCanary][] 蔚落/ 2022年06月09日 13:56/ 0 赞/ 158 阅读
相关 [SQL Server]内存泄露(memory leak)——游标导致的内存问题 转自:[http://blogs.msdn.com/b/apgcdsd/archive/2011/07/01/sql-server-memory-leak.aspx][http 比眉伴天荒/ 2022年06月05日 10:05/ 0 赞/ 185 阅读
相关 利用linux的mtrace命令定位内存泄露 Memory Leak 分享一下我老师大神的人工智能教程!零基础,通俗易懂![http://blog.csdn.net/jiangjunshow][http_blog.csdn.net_jiangju 柔情只为你懂/ 2022年04月17日 00:07/ 0 赞/ 170 阅读
相关 利用linux的mtrace命令定位内存泄露(Memory Leak) 一谈到内存泄露, 多数程序员都闻之色变。 没错, 内存泄露很容易引入, 但很难定位。 以你我的手机为例(假设不经常关机), 如果每天泄露一些内存, 那么开始的一个星期, 你会发 快来打我*/ 2022年02月03日 15:15/ 0 赞/ 302 阅读
相关 VC内存泄露检查工具:Visual Leak Detector [http://www.codeproject.com/KB/applications/visualleakdetector.aspx][http_www.codeprojec 水深无声/ 2021年12月20日 23:17/ 0 赞/ 215 阅读
还没有评论,来说两句吧...