如何检测 ASP.net 应用程序中的 SqlServer 连接泄漏?
Posted
技术标签:
【中文标题】如何检测 ASP.net 应用程序中的 SqlServer 连接泄漏?【英文标题】:How to detect SqlServer connection leaks in a ASP.net applications? 【发布时间】:2010-09-17 18:37:27 【问题描述】:我目前正在对 ASP.net 2.0 应用程序进行一些 GUI 测试。 RDBMS 是 SQL Server 2005。主机是 Win Server 2003 / IIS 6.0。
我没有应用程序的源代码,因为它是由未发布代码的外部公司编写的。
我注意到当我重新启动 IIS 时应用程序运行良好,但经过一些测试,在我打开和关闭浏览器几个小时后,应用程序开始变得越来越慢。我想知道这种行为是否是由于程序员关闭连接的错误做法造成的:我怀疑这里的数据库存在开放连接泄漏。
我猜 .Net 垃圾收集器最终会关闭它们,但是……这可能需要一段时间,不是吗?
我有 SQL Server Management Studio,我确实从活动监视器中注意到在数据库上打开了很多连接。
综上所述,以下是与主要问题相关的一些问题:
有什么方法可以知道SQL Server 2005(如果连接正常) 开放,因为他们正在等待 在连接池中使用,或者如果 它们是开放的,因为它们被 申请?
有人知道善吗 我可以的在线/纸质资源 学习如何使用性能 计数器或其他类型的工具 帮助追踪这些 问题?
如果性能计数器是最好的 解决方案,我的变量是什么 应该看吗?
【问题讨论】:
连接池是否启用? 是的。当我遇到类似问题时,我发现它在应用程序中设置为 false。 一般是开发者设置为关闭,部署后在web.config/connectionstrings中忘记关闭,常见的部署错误 郑重声明,1) 开发人员不应该关闭连接池(为什么无缘无故地让开发环境变得不那么真实?)和 2) 使用连接池和没有连接池一样容易发生泄漏,因此关于连接池的全部观点是完全无关的 【参考方案1】:发现这个线程正在研究类似的问题。我想出了以下 sql 作为调试 SQL Server 中泄漏连接的好方法:
SELECT S.spid, login_time, last_batch, status, hostname, program_name, cmd,
(
select text from sys.dm_exec_sql_text(S.sql_handle)
) as last_sql
FROM sys.sysprocesses S
where dbid > 0
and DB_NAME(dbid) = '<my_database_name>'
and loginame = '<my_application_login>'
order by last_batch asc
这为您提供的是特定数据库和登录上的所有打开连接,以及在该连接上执行的最后一条 sql,按执行该 sql 的时间排序。
由于连接池,您不能仅仅依靠周围有很多连接的事实来告诉您连接泄漏,因为即使连接正确关闭,连接池也会保留连接代码。然而,如果你确实有连接泄漏,你会看到一些连接被“冻结”——它们会出现在上面的查询中,并且“last_batch”时间戳永远不会改变。其他连接也会挂起,但每次在它们上运行新的 sql 时,“last_batch”时间戳都会更新。所以效果是冻结的连接将浮动到这个查询的顶部。
如果您有相关应用程序的源代码,那么这会为您提供在孤立连接上执行的最后一条 sql,这对于调试非常有价值。
注意 'loginame' 的拼写错误(缺少'n')出现在sys.sysprocesses
视图中。上面的说法是正确的。
loginame nchar(128) 登录名。
https://docs.microsoft.com/en-us/sql/relational-databases/system-compatibility-views/sys-sysprocesses-transact-sql?view=sql-server-ver15
【讨论】:
这个查询很有帮助。我能够在短短几分钟内查明我们遇到的严重连接泄漏。谢谢!【参考方案2】:我遇到了这个问题,发现 SQL Server Profiler 是一个很棒的工具,我在一个简短的测试运行中监视了该站点,并注意到正在创建的许多连接 (sp_who) 没有被连接池重用,所以我只打开了 SQL Server Profiler,然后检查是否所有从代码对 SP 的调用都跟在“sp_reset_connection”调用之后。如果在新批次开始之前呼叫不存在,那么您只是缺少第一个连接。
【讨论】:
注意探查器中丢失的“sp_reset_connection”是一个很好的提示,谢谢!【参考方案3】:您可以随时检查 web.config 中的连接字符串(主要是如果它们激活了连接池,是否启用了任何连接限制)。
此外,如果您使用的是 IIS 6,您可以将 Web 应用程序设置为使用单独的应用程序池,并设置其他选项以回收内存和进程。
关于性能计数器,您可以检查垃圾收集器运行了多长时间, 应用程序正在使用多少内存等。
如果您有权访问 sql server,则可以监控从您的应用程序建立的连接(为每个已安装的 SQL Server 实例定义了性能计数器)。
MSDN Magazine中有一些文章。您也可以使用 SOS 调试库附加到应用程序的进程并手动检查它。
而且,如果您没有源代码,请尝试使用Reflector 获取应用程序的源代码(它们对于调试非常有用)
@稍后编辑:您也可以在 ***.com 上查看此question
【讨论】:
【参考方案4】:关于 (ADO.NET performance counters) 的 MSDN 参考非常清楚地说明了在分析应用程序时可以查找的内容。您可以使用 Windows 内置的 perfmon 应用程序来监控计数器。
除此之外,我建议了解 ADO.NET 连接池。如果您真的怀疑他们的代码中存在错误,您可以使用 Red Gate's Reflector(现在免费)查看它,它将 MSIL 反汇编为 C#。
【讨论】:
【参考方案5】:我会首先查看连接并查看活动时间,看看您是否可以找到保持连接打开的项目。
我想说的是,如果解决方案是重新启动 IIS,您还可以查看应用程序的内存使用情况,看看是否存在内存泄漏或确实导致其占用空间增加的情况。
如果打开的连接是一个问题,在活动监视器中,您会看到大量没有活动的连接。
对于性能计数器,您可能会开始查看“SQL Server : General Stats”性能对象。
【讨论】:
【参考方案6】:Todd Denlinger 编写了一个很棒的课程http://www.codeproject.com/KB/database/connectionmonitor.aspx,它监视 Sql Server 连接并报告在一段时间内未正确处理的连接。将其连接到您的站点,它会在发生泄漏时通知您。
【讨论】:
以上是关于如何检测 ASP.net 应用程序中的 SqlServer 连接泄漏?的主要内容,如果未能解决你的问题,请参考以下文章
.NET 程序集如何在 IIS ASP.NET 上下文中检测自己的版本?
ASP.NET MVC:如何在 Global.asax.cs 中的 Application_Start() 中检测浏览器宽度
使用 ASP.NET Core 后端和 React 前端的 Web 应用程序中的授权和身份验证?