如何强制SQL Server释放内存?

22

如何检查当前实际使用了多少内存,以及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 的最大服务器内存降低,然后再增加它以强制 SQL Server 释放未使用但已分配的内存。但是这种方法的问题在于我们无法确定需要减少多少最大服务器内存,因此存在杀死 SQL Server 的风险。这就是为什么在减少最大服务器内存的值之前,了解 SQL Server 实际使用量的重要性。


2
DBCC FREE调用并非旨在将内存释放回操作系统,而仅将与其功能相关的页面标记为可用。一旦服务器分配了内存,它就会保留它,没有理由进行昂贵的重组和刷新,最大内存选项是例外。真正的问题或许是:为什么您需要这样做? - Alex K.
在主动-主动模式下,SQL Server实例有时会占用比实际需要更多的内存,并限制那些迫切需要这些资源的其他实例。除了减少每个节点上的实例数量并增加物理内存之外,是否有更好的解决方法? - Tigerjz32
4
  1. 这个问题应该发布在DBA上。
  2. 不要这样做。告诉SQL Server它可以使用多少内存,它通常会使用它感觉需要的尽可能多的内存,但不会超过设定的限制... 一般情况下,这将是整个数据库加上一些,除非数据库大于内存限制。如果您不希望它这样做,则需要使用“max server memory”设置来设置限制。
- Ben
  1. 好的,下次发布时会记住这一点,除非您能帮忙移动这个问题?
  2. 数据库大小肯定比内存大得多。您说得对,限制最大服务器内存应该解决问题,但请记住,我们正在谈论活动-活动集群。这意味着任何实例都可以托管在任何节点上。这使得分配特定数量的最大服务器内存变得困难。
- Tigerjz32
7个回答

19
下面的修改脚本对我有用。我需要临时释放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  

3

SQL Server总是假定它是主要运行的应用程序。它不设计共享资源。它总是占用所有可用的内存,只有在使用'max server memory'进行限制时才会将其释放给操作系统。

按设计,Sql Server与其他应用程序不兼容。

该sqlskills文章建议设置基线来进行限制,并根据需要监视和提高限制:

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


0

我没有解决如何释放已分配内存的方案。然而,为了我们的目的,我们能够找出如何让活动-活动集群安全运行。我们决定将最小服务器内存设置为约2GB。这很有帮助,因为无论实例决定使用多少最大内存,它都不会使其他实例耗尽内存。所以,这解决了我们的目的,但仍然没有回答实际使用了多少内存,我们可以将最大服务器内存降低到多低等问题...


-1

如果您遇到紧急情况并且可以承受一小段停机时间,只需重新启动SQL服务即可。重新启动只需要几秒钟,并且可以很好地完成工作。右键单击服务器名称,然后单击“重新启动”。


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

-1

很遗憾,这不是我们想要的。正如我在多个评论中提到的那样,我们想要释放内存,而不是限制最大大小,因为这是一个主动-主动集群。 - Tigerjz32

-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是安全的? - Tigerjz32
我认为这取决于许多参数和配置,因此没有安全地将其清除到最小值的选项。即使微软将128 MB设置为最小值,但他们并不推荐这样做。你为什么需要释放它?你在服务器上运行其他消耗大量内存的东西吗? - Anton
服务器运行在一个主动-主动的集群上,这意味着任何实例都可以在任何节点上运行。如果实例A在某个时候分配了比它需要的更多的内存,那么实例B可能没有足够的内存来分配给自己,或者只是有更少的内存可用于工作。为了避免这种情况,我们希望手动释放实例A的内存。释放内存的最佳方法是降低最大内存并再次增加它。要进行降低操作,我们需要知道降低多少才不会影响正在进行的进程。 - Tigerjz32

-1

我认为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/zh-cn/library/ms178067.aspx


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接