如何强制 SQL Server 释放内存?

Posted

技术标签:

【中文标题】如何强制 SQL Server 释放内存?【英文标题】:How do you force SQL Server to release memory? 【发布时间】:2016-12-24 05:54:04 【问题描述】:

检查当前有多少(实际)内存的好方法是什么 正在使用与 SQL Server 为自己分配了多少?

我一直在诉诸 memory_utilization_‌​percentage,但在运行以下释放内存后,这似乎并没有改变。

SELECT  [Memory_usedby_Sqlserver_MB] = ( physical_memory_in_use_kb / 1024 ) ,
        [Memory_utilization_percentage] = memory_utilization_percentage 
FROM    sys.dm_os_process_memory;

DBCC FREESYSTEMCACHE ('ALL')
DBCC FREESESSIONCACHE
DBCC FREEPROCCACHE

SELECT  [Memory_usedby_Sqlserver_MB] = ( physical_memory_in_use_kb / 1024 ) ,
        [Memory_utilization_percentage] = memory_utilization_percentage 
FROM    sys.dm_os_process_memory;

解决方案是删除 SQL Server 的 ma​​x server memory 并再次增加它以强制 SQL Server 释放未使用但已分配的内存。然而,这种方法的一个问题是我们无法确定将 最大服务器内存 减少多少,因此冒着杀死 SQL Server 的风险。这就是为什么在减少 最大服务器内存 值之前了解 SQL Server 的“实际”使用量很重要。

【问题讨论】:

DBCC FREE 调用并非旨在将内存释放回操作系统,它们只是将与其功能相关的页面标记为可用。一旦服务器分配了内存,它就会保留它,它没有理由执行昂贵的重组和刷新,最大内存选项是一个例外。真正的问题可能是为什么你需要这样做? 在主动-主动实例的情况下,SQL Server 实例有时会占用比所需更多的内存,它会限制其他迫切需要它们的实例。除了减少每个节点的实例并增加物理内存之外,有没有更好的方法来解决这个问题? 1) 这个问题属于 DBA。 2)不要这样做。告诉 SQL Server 允许使用多少内存,它通常会根据需要使用多少内存,直到该限制……通常这将是整个数据库的大小加上一些,除非数据库是大于内存限制。如果您不希望它这样做,那么您需要使用 max server memory 设置来设置限制。 1) 好的,下次我发帖时会记住这一点,除非有办法移动这个问题,你可以帮忙吗? 2)数据库大小肯定比内存大得多。您说limit max server memory 应该可以解决问题是正确的,但请记住我们正在谈论主动-主动集群。这意味着任何实例都可以托管在任何节点上。这使得分配特定数量的最大服务器内存变得困难。 【参考方案1】:

您必须将“最大服务器内存”设置为 1-2 GB 之间的某个值。在大多数情况下,这个范围是安全的。下面执行后可能需要一段时间来释放内存:

sp_configure 'show advanced options', 1;  
GO  
RECONFIGURE;  
GO  
sp_configure 'max server memory', 1024;  
GO  
RECONFIGURE;  
GO  

该设置允许清除池、编译内存、所有缓存、clr 内存等。

“最大服务器内存”的最小值为 128 MB,但不建议这样做,因为 SQL Server 在某些配置中可能无法启动。如果发生这种情况,请使用“-f”开关强制以最小配置启动 SQL,然后将值更改为原始值。

【讨论】:

谢谢!但是,有没有办法找出我应该放弃“最大服务器内存”而不是假设 1-2GB 是安全的最低数字? 我不这么认为,因为它取决于许多参数和配置,这就是为什么没有选项可以安全地将其清除到最小值的原因。甚至 MS 设置 128 MB 也是最低要求,但他们不推荐它。为什么需要释放它?您是否在服务器上运行其他消耗大量内存的程序? 服务器在双活集群上运行,这意味着任何实例都可以在给定时间在任一节点上运行。如果实例 A 分配的内存比它当时需要的多,则实例 B 可能没有足够的内存分配给它自己,或者只有更少的内存可供使用。为避免这种情况,我们想手动释放实例 A 的内存。释放内存的最佳方法是删除最大内存并再次增加它。要下降,我们需要知道在不影响正在进行的过程的情况下下降多远。【参考方案2】:

本帖在以下链接中解决,请检查格式:

SQL Server not releasing memory after query executes

【讨论】:

不幸的是它不是。正如我在多个 cmets 中提到的,我们希望释放内存,而不是限制最大大小,因为这是一个主动-主动集群。【参考方案3】:

我没有关于如何释放分配的内存的解决方案。但是,出于我们的目的,我们能够弄清楚如何让主动-主动集群安全运行。我们决定将最小服务器内存设置为 ~2GB。这很有帮助,因为无论实例决定使用多少最大内存,它都不会在内存不足的情况下运行其他实例。因此,这再次解决了我们的目的,但它仍然没有回答实际使用了多少内存、我们可以将最大服务器内存降低到多低等问题......

【讨论】:

【参考方案4】:

我认为 SQL Server 不会释放内存,除非操作系统主动请求它。如果存在其他进程请求更多内存的情况,而如果根本没有,SQL Server 将自行释放未使用的内存。我可能不会尝试刷新未使用的内存,而是限制 SQL 的最大允许内存。

sp_configure 'show advanced options', 1
GO  

RECONFIGURE
GO  

sp_configure 'max server memory', 512; --or some other value
GO  

RECONFIGURE
GO

更多信息,您可以查看这篇 MSDN 文章:https://msdn.microsoft.com/en-us/library/ms178067.aspx

【讨论】:

【参考方案5】:

SQL Server 始终假定它是正在运行的主应用程序。它不是为了共享资源而设计的。它总是会占用所有可用内存,并且只会为操作系统释放它,除非您使用“最大服务器内存”进行节流。

按照设计,Sql Server 不能与其他服务器配合使用。

这篇 sqlskills 文章推荐了一个限制基线,然后根据需要监控和提高限制:

https://www.sqlskills.com/blogs/jonathan/how-much-memory-does-my-sql-server-actually-need/

【讨论】:

【参考方案6】:

以下修改后的脚本对我有用。我需要暂时释放 SQLServer 持有的一堆 RAM,以便我们可以在同一台服务器上运行一些其他一次性进程。它会暂时释放 SQL 保留的内存空间,同时仍允许它根据需要吞噬内存。

我添加了一个内置的等待功能,让 SQLServer 在将内存恢复到原始级别之前实际释放内存。显然根据需要调整值以满足您的需要。

sp_configure 'show advanced options', 1;  
GO  
RECONFIGURE;  
GO  
/*** Drop the max down to 64GB temporarily ***/
sp_configure 'max server memory', 65536;  --64GB
GO  
RECONFIGURE;  
GO  
/**** Wait a couple minutes to let SQLServer to naturally release the RAM..... ****/
WAITFOR DELAY '00:02:00'; 
GO
/** now bump it back up to "lots of RAM"! ****/
sp_configure 'max server memory', 215040;    --210 GB
GO  
RECONFIGURE;    
GO  

【讨论】:

【参考方案7】:

以防万一您处于紧急情况并且可能会出现短暂的停机时间,只需重新启动您的 SQL 服务即可。只需几秒钟即可重新启动并很好地完成工作。右键单击您的服务器名称,然后单击重新启动。

【讨论】:

正确,重置可能会释放内存,但这在任何生产环境中都很难做到。在我看来,更好的解决方案是找到杀死正在使用临时表的活动任务。

以上是关于如何强制 SQL Server 释放内存?的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 缓存清除与内存释放

SQL Server 缓存清除与内存释放

ms sql server缓存清除与内存释放

sqlserver内存释放

如何强制通用应用程序释放内存?

强制向操作系统释放内存