SQL Server 2012 缓冲池外的内存消耗

dba*_*old 10 sql-server memory sql-server-2012

我有一个 SQL Server 2012 SP2 企业版的实例,它消耗的内存比最大值高约 20GB。内存限制。实例限制为 65GB,但以下查询中使用的物理内存显示为 86GB

SELECT (physical_memory_in_use_kb/1024)/1024 AS [PhysicalMemInUseGB]
FROM sys.dm_os_process_memory;
GO
Run Code Online (Sandbox Code Playgroud)

服务器是具有 2 个 NUMA 节点的物理服务器。有没有一种方法可以找出正在消耗缓冲池之外的内存的东西(我假设这就是正在发生的事情)?

这是 DBCC MEMORYSTATUS 的输出:-

DBCC MEMORYSTATUS 的输出

这是设置的内存限制:-

内存限制的屏幕截图

提前致谢。

更新:-我已经运行了 Aaron 建议的查询

SELECT TOP (20) * FROM sys.dm_os_memory_clerks ORDER BY pages_kb DESC
Run Code Online (Sandbox Code Playgroud)

这是输出:-

内存职员输出

pages_kb 的总和达到 ~60GB

更新 2:- DBCC MEMORYSTATUS 的完整输出在这里:- http://pastebin.com/nGn6kXEc

更新 3:- 此处在 excel 文件中输出 Shanky 的脚本:- http://jmp.sh/LKRlH4K

更新 4:- 输出的屏幕截图:-

SELECT (physical_memory_in_use_kb/1024)/1024 AS [PhysicalMemInUseGB]
FROM sys.dm_os_process_memory;
GO
Run Code Online (Sandbox Code Playgroud)

PhysMemInUse 截图

所以这似乎表明 SQL Server 正在使用超过 65GB 的设置。

Aar*_*and 11

最大服务器内存控制缓冲池和所有页面大小分配,但仍不控制直接 Windows 分配(链接服务器、sp_OA、XP)、线程/线程堆栈所需的内存等

您可能会期望在 NUMA 上这会更高(尽管我不确定 20 GB 是否正常);关键是,您不能期望最大服务器内存能够完全控制 SQL Server 实例使用的内存。如果您希望整个实例(不仅仅是缓冲池、计划缓存和 CLR)使用不超过 64GB,您应该将最大服务器内存设置为更低。

追踪这个问题的一些潜在想法(我会将所有内容标准化为 MB):

  • 性能计数器

    看看这里是否有太大的东西跳出来:

    SELECT counter_name, instance_name, mb = cntr_value/1024.0
      FROM sys.dm_os_performance_counters 
      WHERE (counter_name = N'Cursor memory usage' and instance_name <> N'_Total')
      OR (instance_name = N'' AND counter_name IN 
           (N'Connection Memory (KB)', N'Granted Workspace Memory (KB)', 
            N'Lock Memory (KB)', N'Optimizer Memory (KB)', N'Stolen Server Memory (KB)', 
            N'Log Pool Memory (KB)', N'Free Memory (KB)')
      ) ORDER BY mb DESC;
    
    Run Code Online (Sandbox Code Playgroud)
  • 前 20 名文员

    您已经这样做了,但为了完整起见:

    SELECT TOP (21) [type] = COALESCE([type],'Total'), 
      mb = SUM(pages_kb/1024.0)
    FROM sys.dm_os_memory_clerks
    GROUP BY GROUPING SETS((type),())
    ORDER BY mb DESC;
    
    Run Code Online (Sandbox Code Playgroud)
  • 线程堆栈大小

    首先,确保这是零,而不是某个自定义数字(如果它不是 0,找出原因并修复它):

    SELECT value_in_use
      FROM sys.configurations 
      WHERE name = N'max worker threads';
    
    Run Code Online (Sandbox Code Playgroud)

    但是您还可以使用以下命令查看线程堆栈占用了多少内存:

    SELECT stack_size_in_bytes/1024.0/1024 
      FROM sys.dm_os_sys_info;
    
    Run Code Online (Sandbox Code Playgroud)
  • 加载了第 3 方模块

    SELECT base_address, description, name
      FROM sys.dm_os_loaded_modules 
      WHERE company NOT LIKE N'Microsoft%';
    
    -- you can probably trace down memory usage using the base_address
    
    Run Code Online (Sandbox Code Playgroud)
  • 与记忆相关的 DMV

    您还可以通过查看这些 DMV 发现一些不寻常的东西:

    SELECT * FROM sys.dm_os_sys_memory;
    SELECT * FROM sys.dm_os_memory_nodes WHERE memory_node_id <> 64;
    
    Run Code Online (Sandbox Code Playgroud)

这篇文章是在 SQL Server 2012 之前写的,所以可能需要调整一些列名和计算,但也可以提供一些其他途径来尝试:

在该网站的另一篇文章中也有一些很好的背景:

关于在外部使用内存的事物类型的一些很好的信息max server memory(但没有关于如何收集实际使用情况的好数据):