KB3074434 - 修复:当SQL Server进程的虚拟地址空间在可用内存上非常低时出现内存不足错误

应用对象
SQL Server 2012 Service Pack 3 SQL Server 2012 Developer SQL Server 2012 Enterprise SQL Server 2012 Enterprise Core SQL Server 2012 Standard

应用此更新后,必须添加跟踪标志 -T8075 作为启动参数才能启用此更改。

症状

在 64 位版本的 Microsoft SQL Server 2012 中运行查询时,会收到一条内存不足错误消息,类似于SQL Server错误日志中的以下内容:

注意

分配页失败:FAIL_PAGE_ALLOCATION 513

查询需要很长时间才能完成执行,并遇到SOS_MEMORY_TOPLEVELBLOCKALLOCATOR等待。

检查以下信息点时,你会发现虚拟地址空间非常少:

  • DBCC MEMORYSTATUS - 进程/系统计数部分 - 可用虚拟内存
  • DMV:sys.dm_os_process_memory - 列virtual_address_space_available_kb

在 x64 进程中,这些值从大约 8 TB (TB) 开始,然后继续向下攀升, (GB) 达到几千兆字节。 

当处于可用虚拟地址空间非常少的阶段时,尝试执行内存分配的查询也可能会遇到等待类型的 CMEMTHREAD。

随着时间推移,以下数据点将继续增加:

  • DMV:sys.dm_os_process_memory和sys.dm_os_memory_nodes - 列virtual_address_space_reserved_kb
  • DBCC MEMORYSTATUS - 内存管理器部分 - VM 保留

这些值通常以“最大服务器内存”值的倍数增加,高达近 8 TB。

原因

当SQL Server进程达到总服务器内存 = 目标服务器内存 = 最大服务器内存的状态时,SQL Server内存管理器中有策略允许新分配请求多个 8 KB 页以暂时成功。 在这种情况下,重复分配模式可能会导致内存块碎片和虚拟地址空间消耗。 如果此过程重复多次,SQL Server虚拟地址空间将耗尽,并且你会注意到前面提到的症状。

解决方法

累积更新信息

此问题首先在以下SQL Server累积更新中得到解决。

建议:为SQL Server安装最新的累积更新

SQL Server的每个新累积更新都包含以前的累积更新中包含的所有修补程序和所有安全修补程序。 建议下载并安装SQL Server的最新累积更新:

此修补程序可防止内存不足和可能遇到的可用虚拟地址空间持续减少。

状态

Microsoft 已确认在 "适用于" 部分中所列的 Microsoft 产品中存在问题。

详细信息

  • Windows 2012 R2 允许虚拟地址空间增长到 128 TB。 因此,在 Windows 2012 R2 环境中,你可能没有注意到此问题。 有关详细信息,请参阅 Windows 开发人员中心中的以下主题:

    Windows 和 Windows Server 版本的内存限制

  • 如果在应用修补程序后看到虚拟地址空间的持续增长,则可以通过使用 Page_allocated扩展事件来确定哪些查询或操作正在请求大块内存。 示例脚本如下所示:

    CREATE EVENT SESSION [memory_tracking] ON SERVER
    ADD EVENT sqlos.page_allocated(
        ACTION(package0.callstack,sqlos.cpu_id,sqlos.task_address,sqlos.worker_address,sqlserver.database_id,sqlserver.query_hash,sqlserver.request_id,sqlserver.session_id,sqlserver.sql_text)
        WHERE ([number_pages]>(1)))
    ADD TARGET package0.event_file(SET filename=N'E:\Data\MSSQL11.MSSQLSERVER\MSSQL\Log\memory_tracking.xel')
    WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=PER_CPU,TRACK_CAUSALITY=OFF,STARTUP_STATE=OFF)
    GO
    
    
    

    这些操作通常是经常发生的日志备份和索引维护操作。