当SQL Server没有可用的物理内存时会发生什么?


16

在进行谷歌搜索时,我发现了一些相互矛盾的信息。

一些站点指出,当没有物理内存可用于数据时,SQL Server会将已存在的数据移至TEMPDB中(请参阅:SQL Server:使TempDb神秘化和建议)。

但是其他站点指出,当剩余的物理内存不足时,操作系统可以使用PAGE FILE并将数据从物理内存移至该页面(请参阅SQL Server的页面文件)。

我想知道当SQL Server的物理内存用尽时,它将在哪里写入数据?要tempdb还是OS页面文件?还是两者都可以?

Answers:


28

当没有剩余物理数据存储空间时,SQL Server将已存在的数据移动到TEMPDB中

您链接到的文章充其量是令人误解的,在某些地方是不正确的。我认为作者试图过分简化一些复杂的事情,这样做有点太过分了。

SQL Server不会以这种方式将数据从内存(缓冲池)移到tempdb中。它使用“最近最少使用”的缓存策略(通常),因此,如果存在内存压力,并且需要将新数据拉入内存,SQL Server将从缓冲池中踢出LRU数据以容纳新数据。此行为通常由称为“页面预期寿命”(PLE)的性能计数器监控:

PLE的定义是读入缓冲池(数据文件页的内存中高速缓存)的数据文件页在被推出内存以为其他数据腾出空间之前将保留在内存中的预期时间(以秒为单位)文件页面。考虑PLE的另一种方法是瞬时测量缓冲池上的压力,以便为从磁盘读取的页面腾出可用空间。对于这两个定义,数字越大越好。

在查询执行期间,SQL Server 可以将tempdb用于某些操作。通常在估计错误的情况下执行此操作,但是可用内存不足会影响此行为。

可以通过这种方式“溢出”到tempdb的一些操作是对行进行哈希处理(用于联接或聚合等),对内存中的行进行排序以及在并行查询执行期间对行进行缓冲。

用户查询还可以显式使用tempdb(具有全局或本地临时表),并隐式使用tempdb(具有快照或读取已提交的快照隔离级别)。

这些情况似乎都不符合您引用的陈述。

当剩余的物理内存不足时,操作系统可以使用PAGE FILE并将数据从物理内存移至其中

这肯定可以发生,并且在大多数情况下是SQL Server无法控制的。您可以旋转一个旋钮来尝试阻止某些类型的OS级分页,即打开“锁定内存中的页面”(LPIM)

此Windows策略确定哪些帐户可以使用进程将数据保留在物理内存中,从而防止系统将数据分页到磁盘上的虚拟内存。

那么我们能防止什么被分页到磁盘?

在SQL Server 2012之前,通过称为“单页分配器”的组件分配的页面已锁定在内存中(无法分页)。这包括缓冲池(数据库页),过程高速缓存以及其他一些内存区域。

有关详细信息,请参阅“ 与锁定页面一起使用,AWE,任务管理器和工作集… ”,尤其是“ 4.现在,我知道x64上的SQL Server可以使用“锁定页面”,到底是什么被锁定了?”。可以在这里找到其他相关的阅读材料:出色的SQL Server辩论:锁定内存中的页面

在SQL Server 2012和更高版本中,没有“单页分配器”(根据深入了解内存– SQL Server 2012/2014,合并了单页分配器和多页分配器)。我见过的任何地方都没有详细记录确切,可以和不能寻呼的内容。您可以使用查询这样的,看看有什么锁定:

select osn.node_id, osn.memory_node_id, osn.node_state_desc, omn.locked_page_allocations_kb
from sys.dm_os_memory_nodes omn
inner join sys.dm_os_nodes osn on (omn.memory_node_id = osn.memory_node_id)
where osn.node_state_desc <> 'ONLINE DAC'

根据同一篇MS Support文章,您还可以DBCC MEMORYSTATUS用来查看“锁定”了多少内存。

作为附带说明,您可以在错误日志中看到操作系统分页显示SQL Server工作集的证据。将显示如下消息:

2019-09-02 10:19:27.29 spid11s sql服务器进程内存的很大一部分已被调出。这可能会导致性能下降。持续时间:329秒。工作集(KB):68780,已落实(KB):244052,内存利用率:28%。


0

现代版本的SQL Server挂断的可能性很小。SQL Server将.NET Framework加载到其地址空间中,并在正常操作下使用它。如果物理内存和页面文件都用完了,Windows将尝试增加页面文件;但是,即使它可以增长页面文件,也不是瞬时操作,并且在增长页面文件时内存分配失败。.NET异步I / O处理程序中存在一个错误,该错误会在其中响应APC通知分配内存。如果调用new失败,它将抛出OutOfMemoryException。任务调度程序中的本机代码中捕获了此异常;但是异步I / O似乎永远不会完成。FileStream的终结器线程将阻止等待I / O完成,以便可以取消固定缓冲区,从而永久挂起终结器线程。这将导致.NET Framework逐渐消耗越来越多的内存,直到无法分配更多的内存为止,此时SQL Server将无响应,因为Winsock无法再分配任何缓冲区,因此,即使管理员访问连接也无济于事。

由于内存不足,我实际上在.NET应用程序中遇到了任务计划程序的总挂断。值得庆幸的是,该过程最终由于OutOfMemoryException在几次失败后抛出无法捕获该线程的线程而最终终止,因此我们可以弄清实际上是什么导致服务器挂机。

一旦知道了要查找的内容,就可以轻松地找到静态分析中的错误。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.