在我之前的博文中(SQL Server内存泄漏),我解释了如何使用“!heap”命令识别哪个模块泄漏了内存。有时我们使用“!d”命令来找到模型或者使用搜索内存命令(s)不能通过显示内存找到原因。
在这种情况下,我们可以使用Debug Diagnostic Tools或者UMDH来跟踪内存泄漏。这篇博文解释了如何使用Debug Diagnostics Tools来识别内存泄漏。
下载并安装Debug Diagnostic Tools从http://www.microsoft.com/en-us/download/details.aspx?id=26798
1.定位到Tools,“Options”->“Preferences”,选择“Record call stacks immediately when monitoring the leaks”。
2.定位到“rules”标签页,并选择“add rule”。
3.选择“Naive(non .Net) memory leak and handle leak”。
4.选择SQL Server或者跟踪用于内存泄漏的任何进程。
5.点击“Next”并保留默认选项(当规则是完成或失效时,你可以选择“auto-unload Leak track”)。
6.点击“Next”并现在激活规则。
7.Leaktrack.dll已经加入到用于跟踪分配的进程里。
8.现在你可以等待泄漏再次发生。
1
2
3
4
5
6
7
|
-- If you are learning how to troubleshoot SQL Server memory leak follow the steps which we followed in previous post (https://mssqlwiki.com/2012/12/04/sql-server-memory-leak/)to leak the memory. -- Download HeapLeak.dll from this link. -- Create an extended stored procedure in SQL Server sp_addextendedproc ‘HeapLeak’,‘C:\HeapLeakdll\HeapLeak.dll’ -- Let us execute this Extended SP 30 times and leak memory. exec HeapLeak
go 30 |
9.当你猜测内存泄漏时,定位到“rules”,并通过右击“Leak rule”执行一个完整的用户dump。
10.在dump被捕获后,定位到高级分析标签页,添加数据文件并选择我们生成的dump。
11.定位到Tools,“Options”->“set the symbol path for analysis”。默认的Microsoft symbol path在下面。
srv*c:\Websymbols*http://msdl.microsoft.com/download/symbols;c:\Release
重要的:使用加载到SQL Server里的DLL的符号路径替代c:\Release (可选的)
12.在可用的分析脚本,选择内存压力分析器(memory analysis.asp)。
13.点击“Start Analysis”。
14.根据加载符号的时间消耗,分析可能要花费一点时间。当分析完成,会生成并打开一个HTML报告。这个HTML报告默认存储在C:\Program Files\DebugDiag\Reports\ 可以用于后续参考。
我附加了一个使用heapleak.dll内存泄漏时收集的示例报表,在这里http://sdrv.ms/TH1qfR。你可以使用它作为参考。
Debug Diagnostic Tool的内存压力分析器生成的报表有分析总结和以下表格内存。
1
2
3
4
5
6
7
|
sqlservr.exe__…………dmp Virtual Memory Analysis Report
Heap Analysis Report
Leak Analysis Report
Outstanding allocation summary
Detailed module report (Memory)
Detailed module report (Handles)
|
15.分析总结是报表中不错部分定位哪个模块泄漏了内存。查看以下报表。
16.报表已清晰的表明HeapLeak.dll有255MB显著的分配。在heapleak.dll里“Sub”函数用于在偏移量23处分配了该内存。
17.查看虚拟内存总结。它给出了在虚拟地址孔家哪里关于内存分布的完整图片。在以下摘要里保留是1.57GB,这在32位SQL Server里是正常的,但是本地堆内存有272.94MB是不正常的。
查看堆摘要,有50个堆。
18.现在查看显著的分配总结。它给出了分配总数和分配大小的前10个模块。在以下摘要HeapLeak占用255.6MB大小里的26182。
注意:在这个报表里它是HeapLeak,但是在实践中它可能是泄漏内存的任何模块。
19.你也可以查看详细的模块报告(Memory)。它给出了内存分配,从每个模块以及函数和分配内存的源行(如果你对所有加载的模块设置符号)。
现在我们确认HeapLeak.dll里的Sub函数在行号为14位置分配了255MB,并且未释放。这个报表也给你callstack示例,显示了当函数分配内存时的代码路径。参考示例HTML报表文件http://sdrv.ms/TH1qfR。