SQL Server 内存泄露(memory leak)——游标导致的内存问题

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介: 原文: SQL Server 内存泄露(memory leak)——游标导致的内存问题 转自:http://blogs.msdn.com/b/apgcdsd/archive/2011/07/01/sql-server-memory-leak.aspx 问题描述:客户反映SQL Server运行一段时间就会报出内存不足的错误,怀疑是有内存泄露。
原文: SQL Server 内存泄露(memory leak)——游标导致的内存问题

转自: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

一旦我们使用了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;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占用了大量的内存,数据库报出内存不足的错误。

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
3月前
|
Arthas 监控 Java
Arthas memory(查看 JVM 内存信息)
Arthas memory(查看 JVM 内存信息)
152 6
|
2月前
|
Arthas 监控 Java
Arthas mc(Memory Compiler/内存编译器 )
Arthas mc(Memory Compiler/内存编译器 )
55 6
|
4月前
|
SQL 监控 数据库
如何解决 SQL Server 占用内存过多问题
SQL Server 占用过多内存会导致响应缓慢和查询性能低下。解决流程包括:1) 查看内存使用情况,2) 分析各数据库内存占用,3) 优化 SQL Server 配置(如限制最大内存),4) 优化查询(如创建索引),5) 持续监控效果。通过这些步骤可有效控制内存占用,提升系统性能。
537 0
|
7月前
|
存储 缓存 数据安全/隐私保护
DMA(Direct Memory Access):直接内存访问
DMA(Direct Memory Access)是一种允许外设直接与内存进行数据传输的技术,无需 CPU 干预。它通过减轻 CPU 负担、提高数据传输效率来提升系统性能。DMA 的工作模式包括直接模式和 FIFO 模式,数据传输方式有单字传送和块传送,寻址模式有增量寻址和非增量寻址。通过缓存一致性协议、同步机制、数据校验和合理的内存管理,DMA 确保了数据在内存中的一致性和完整性。
890 0
|
9月前
|
Rust 编译器
|
10月前
|
存储 网络协议 大数据
一文读懂RDMA: Remote Direct Memory Access(远程直接内存访问)
该文档详细介绍了RDMA(远程直接内存访问)技术的基本原理、主要特点及其编程接口。RDMA通过硬件直接在应用程序间搬移数据,绕过操作系统协议栈,显著提升网络通信效率,尤其适用于高性能计算和大数据处理等场景。文档还提供了RDMA编程接口的概述及示例代码,帮助开发者更好地理解和应用这一技术。
|
10月前
|
关系型数据库 MySQL 网络安全
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
|
11月前
|
设计模式 uml
在电脑主机(MainFrame)中只需要按下主机的开机按钮(on()),即可调用其它硬件设备和软件的启动方法,如内存(Memory)的自检(check())、CPU的运行(run())、硬盘(Hard
该博客文章通过一个电脑主机启动的示例代码,展示了外观模式(Facade Pattern)的设计模式,其中主机(MainFrame)类通过调用内部硬件组件(如内存、CPU、硬盘)和操作系统的启动方法来实现开机流程,同时讨论了外观模式的优缺点。
|
11月前
|
SQL 存储 缓存
SQL Server 内存占用较高 - 清除缓存 或 设置内存最大占用值
SQL Server 内存占用较高 - 清除缓存 或 设置内存最大占用值
397 0
|
11月前
|
SQL 安全 Java
驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。错误:“The server selected protocol version TLS10 is not accepted by client
驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。错误:“The server selected protocol version TLS10 is not accepted by client
743 0

热门文章

最新文章