什么是控制 SQL Server 的页面文件使用?SQL Server 还是 Windows?

Max*_*iga 6 sql-server

如果未启用内存中的锁定页面并且 SQL Server 数据被调出到页面文件,SQL Server 是否会决定哪些数据被调出?或者这是由操作系统处理的?

如果 Windows 正在处理这个问题,它会告诉 SQL Server 哪些数据已被调出吗?据我了解,SQL Server 知道 RAM 中有多少数据以及页面文件中有多少数据。但是 SQL Server 是否知道将哪些数据页放在哪里,它是否对数据页放在其中一个或另一个有任何影响?

这是一些背景:

我并不是真的想解决这样的问题。

我的问题更多是关于了解 SQL Server 内部发生了什么......

我遇到了一个应用程序的问题,该应用程序有很长的作业/查询队列,等待 SQL Server 实例处理请求超时。我注意到有问题的数据库上的两个 SELECT 查询短暂地阻塞了一个 UPDATE 和一个 DELETE 查询。不久之后,两个新的 SELECT 阻塞了两个新的 UPDATE 和 DELETE 查询。这继续。

SQL Server 按预期工作 - 只是对于遇到超时的应用程序来说太慢了。

SQL Server 实例位于具有 14 个其他 SQL Server 实例的主动/被动群集上。

我与应用程序开发人员一起解决了这个问题。我们讨论了为实例分配更多 RAM,虽然我并不真正认为这会帮助我将最大服务器内存 (MB) 设置从 40GB 提高到 55GB。在几秒钟内,所有作业在执行的应用程序服务器上排队等待——开发人员正在看着它们非常迅速地从队列中被删除。

托管 SQL Server 的服务器当时没有设置为允许服务帐户在内存中锁定页面,所以我在想,如果处理提到的请求所需的数据放在页面文件中,以及何时分配额外的 RAM数据从页面文件移动到 RAM 也许这可以解释为什么所有作业在分配额外的 RAM 后立即完成得如此之快。

Ton*_*kle 12

首先,您真正需要知道的最重要的事情是配置 SQL Server 和系统上其他应用程序的内存使用情况以确保它永远不会开始分页到磁盘是至关重要的。RAM 访问以纳秒为单位,而磁盘访问以毫秒为单位,因此任何被调出的内容都将花费数百甚至数千倍的时间来访问。它还会在系统上产生大量 I/O 负载以进行交换、争夺内存、CPU 和磁盘访问。因此,即使您有 SSD,如果它开始交换到磁盘,它仍然会受到伤害。

当最大内存设置更改时,SQL Server 会丢弃缓冲区中的所有内容并重新开始。因此,如果它正在将缓冲区交换到磁盘,是的,这可能会导致磁盘交换停止并且性能有所恢复。但是,如果它正在交换到具有 40 GB 设置的磁盘,那么由于它将使用更多内存,因此将来更有可能进行交换。

但是,您所做的更改可能只是巧合——您确定没有长时间运行的查询阻塞这些作业吗?有许多可能的原因,除非您有来自监控机制的数据,否则此时无法确定。

避免交换到磁盘的内存管理是在一个系统上运行多个 SQL Server 实例的危险之一。例如,如果您有 128 GB 的 RAM,则所有实例的最大内存设置总共应该只有 110 GB 左右,在监视可用内存一段时间后可能会多出几 GB

如果 SQL Server 无法锁定内存中的页面,则它无法控制将哪些内存交换到磁盘。一个进程有一个虚拟内存的地址空间,当进程读取内存时,操作系统会从物理位置(内存或磁盘)中检索它。操作系统会跟踪上次访问内存的时间,并尝试调出最不活跃的内存以减少影响。

该进程不知道其虚拟内存的每个偏移量的物理位置——这可能会在跟踪它时产生大量毫无意义的开销。但是,SQL Server 确实有办法知道有多少内存被交换到磁盘,因为当它达到某个阈值时,它会记录一条消息,如如何减少 SQL Server 中缓冲池内存的分页中所示

强烈推荐阅读:Windows 中的 RAM、虚拟内存、页面文件和内存管理,特别是要了解监视内存、页数/秒不是交换到磁盘的内存的有效度量。Internet 上的许多其他文章错误地建议使用此计数器。

Memory, Pages/Sec:这个计数器是最容易被误解的度量之一。

此计数器的高值并不一定意味着您的性能瓶颈源于 RAM 不足。由于内存过量使用,操作系统将分页系统用于交换页面以外的目的。

您可以通过简单地让应用程序将大量数据写入磁盘来轻松验证这一点,并且您会看到内存、页数/秒的高数字。这是因为写入磁盘的数据首先必须在内存中,然后再“分页”到磁盘。围绕“寻呼”的术语是由许多系统管理员误解,它常常被定义为“交换过程中的工作组到磁盘”,但“寻呼”比覆盖更广泛的长期每次读取和写入磁盘。


Joh*_* N. 5

多次阅读您的问题后,我的印象是您可能混合了一个或其他内存管理问题。无论是从操作系统角度还是从 SQL Server 内存管理角度来看。

我们一步一步来,然后再从后面卷起来。

分页问题和 SQL Server

如果 SQL Server 确实遇到了将 SQL Server 内存分页到磁盘的问题,那么您将在 SQL Server 实例的 ERRORLOG 文件中找到与以下内容相关的以下错误消息error 17890

A significant part of sql server process memory has been paged out. 
This may result in a performance degradation. Duration: #### seconds. 
Working set (KB): ####, committed (KB): ####, memory utilization: ##%.
Run Code Online (Sandbox Code Playgroud)

参考:内存管理架构指南(Microsoft | SQL 文档)
参考:服务器内存配置选项(Microsoft | SQL 文档)

此问题可能与内存中的锁定页面设置有关,并在 Microsoft 文章内存管理架构指南(Microsoft | SQL Docs)中进行了记录。解决方案是打开“Lock Pages in Memory”选项,但是......

仅在必要时使用,即有迹象表明 sqlservr 进程正在被调出。

...这将在错误日志中提到。(向上滚动查看错误消息

最大服务器内存

要查看实例上正在消耗 SQL Server 缓冲区缓存的内容,请运行以下命令:

缓冲区语句分组

SELECT
    (CASE WHEN ([database_id] = 32767)
        THEN N'Resource Database'
        ELSE DB_NAME ([database_id]) END) AS [DatabaseName],
    COUNT (*) * 8 / 1024 AS [MBUsed],
    SUM (CAST ([free_space_in_bytes] AS BIGINT)) / (1024 * 1024) AS [MBEmpty]
FROM sys.dm_os_buffer_descriptors
GROUP BY [database_id];
GO
Run Code Online (Sandbox Code Playgroud)

该声明将...

返回有关当前 SQL Server 缓冲池中的所有数据页的信息。该视图的输出可用于根据数据库、对象或类型确定缓冲池中数据库页的分布。

参考:sys.dm_os_buffer_descriptors (Transact-SQL)(Microsoft | SQL 文档)

在对托管 AdventureWorks2012 和 AdventureWorks2012DW 数据库的实例运行 Buffer Statement Grouped 查询之前,我通过发出以下命令确保我的实例在缓冲区缓存中存储了一些数据:

select 'SELECT * FROM ' + ss.name + '.' + sao.name + ' where 1=1' from sys.all_objects sao join sys.schemas as ss on ss.schema_id = sao.schema_id
where sao.type = 'U' and sao.is_ms_shipped = 0
Run Code Online (Sandbox Code Playgroud)

...然后针对 AdventureWorks2012 和 AdventureWorks2012DW 数据库运行输出。然后我sys.dm_os_buffer_descriptors用脚本查询管理视图并收到以下结果:

      DatabaseName     | MBUsed | MBEmpty 
 ----------------------|--------|--------- 
  AdventureWorksDW2012 |    103 |       6 
  AdventureWorks2012   |     95 |       9 
Run Code Online (Sandbox Code Playgroud)

SQL Server 已将我查询的一些数据存储在 SQL Server 缓冲区中。问题是,如果我增加最大服务器内存(MB)设置,它会改变吗?我当前的设置是 1024 MB。然后我将该值增加到 2048 MB:

sp_configure 'show advanced options', 1
go
reconfigure
go
sp_configure 'max server memory (MB)', 2048
go
reconfigure
Run Code Online (Sandbox Code Playgroud)
Configuration option 'show advanced options' changed from 1 to 1. Run the RECONFIGURE statement to install.  
Configuration option 'max server memory (MB)' changed from 1024 to 2048. Run the RECONFIGURE statement to install.
Run Code Online (Sandbox Code Playgroud)

...并再次查询sys.dm_os_buffer_descriptors管理视图:

      DatabaseName     | MBUsed | MBEmpty 
 ----------------------|--------|--------- 
  AdventureWorksDW2012 |      2 |       0 
  AdventureWorks2012   |      3 |       0 
Run Code Online (Sandbox Code Playgroud)

如您所见,更改最大服务器内存 (MB)设置将刷新 SQL Server 缓冲区缓存(数据)和其他内容,这可以在 ERRORLOG 文件中观察到:

2020-01-30 08:33:17.17 spid55      Configuration option 'show advanced options' changed from 1 to 1. Run the RECONFIGURE statement to install.
2020-01-30 08:35:23.74 spid55      Configuration option 'show advanced options' changed from 1 to 1. Run the RECONFIGURE statement to install.
2020-01-30 08:35:23.75 spid55      Configuration option 'max server memory (MB)' changed from 1024 to 2048. Run the RECONFIGURE statement to install.
2020-01-30 08:35:23.75 spid55      SQL Server has encountered 1 occurrence(s) of cachestore flush for the 'Object Plans' cachestore (part of plan cache) due to some database maintenance or reconfigure operations.
2020-01-30 08:35:23.75 spid55      SQL Server has encountered 1 occurrence(s) of cachestore flush for the 'SQL Plans' cachestore (part of plan cache) due to some database maintenance or reconfigure operations.
2020-01-30 08:35:23.75 spid55      SQL Server has encountered 1 occurrence(s) of cachestore flush for the 'Bound Trees' cachestore (part of plan cache) due to some database maintenance or reconfigure operations.
Run Code Online (Sandbox Code Playgroud)

由于 SQL Server 缓存已被刷新,因此现在必须针对数据库运行的任何查询将有足够的内存来:

  • 制定新的执行计划
  • 将数据存储在内存中

您的实例能够跟上用户请求,直到正常用户请求可能阻碍您所讨论的队列为止,因为 SQL Server 将根据命中数据库引擎的查询来优化可用内存。

分页和 SQL Server

微软写道:

Microsoft SQL Server 根据系统当前负载和活动的内存需求执行动态内存管理。在 Windows 上,SQL Server 可以使用 QueryMemoryResourceNotification Windows API 提供的内存通知机制。根据来自 QueryMemoryResourceNotification Windows API 或内存计算的信息,SQL Server 对特定系统上的当前内存情况做出响应。这提供了以下好处:
- 系统不会调出 SQL Server 进程的工作集。
- 必要的数据库页在内存中可用,以减少物理 I/O 需求。
有关详细信息,请参阅 SQL Server 联机丛书中的“动态内存管理”主题和“服务器内存选项”主题。

参考:如何减少 SQL Server 中缓冲池内存的分页(Microsoft 支持)

重要的

警告上述文章中
有一个解决方法如何解决此问题部分。请先阅读如何解决此问题

如果您遇到 SQL Server 分页工作集数据的问题,则会在错误日志中对此进行注释。然后,您可以确定是否需要对 SQL Server 进行故障排除并可能在内存中配置锁定页。

但是,如果您的最大服务器内存 (MB)设置太低,则您可能会遇到 ERRORLOG 消息,但可以通过增加最大服务器内存 (MB)设置来缓解该问题,而无需设置“锁定内存页面”权限。

我通过以下方式在我的 SQL Server 实例上重现了此问题:

  • 减少最大服务器内存 (MB)
  • 执行巨大的选择
  • 检查错误日志
  • 再次增加最大服务器内存 (MB)设置

我观察到,当我没有足够的内存时,分页实际上是一个问题:

2020-01-30 09:13:30.69 spid23s     A significant part of sql server process memory has been paged out. This may result in a performance degradation. Duration: 0 seconds. Working set (KB): 177204, committed (KB): 347808, memory utilization: 50%.
2020-01-30 09:13:33.69 spid23s     A significant part of sql server process memory has been paged out. This may result in a performance degradation. Duration: 0 seconds. Working set (KB): 164596, committed (KB): 334896, memory utilization: 49%.
Run Code Online (Sandbox Code Playgroud)

从时间戳可以看出,这些测试是在我的 SQL Server 实例上按顺序执行的

再次增加内存,减少分页。

解决方案

  1. 如果您有内存可用,请增加最大服务器内存 (MB)参数。这可以减少分页(如我的案例所示)。
  2. 如果您没有可用的内存,请按照我引用的文章中的如何解决此问题进行操作。
  3. 如果所有其他方法都失败,请考虑在内存配置中设置锁定页面。

回答你的问题

什么控制 SQL Server 的页面文件使用?SQL Server 还是 Windows?

我将再次引用我引用的内存管理架构文档并强调一些要点

SQL Server 数据库引擎的默认内存管理行为是获取所需的尽可能多的内存,而不会造成系统内存短缺。SQL Server 数据库引擎通过使用 Microsoft Windows 中的内存通知 API 来完成此操作。

当 SQL Server 动态使用内存时,它会定期查询系统以确定可用内存量。维护此空闲内存可防止操作系统 (OS) 进行分页。如果可用内存较少,SQL Server 会将内存释放给操作系统。如果有更多可用内存,SQL Server 可能会分配更多内存。SQL Server仅在其工作负载需要更多内存时才添加内存;静态服务器不会增加其虚拟地址空间的大小。

SQL Server 根据操作系统的要求/需要向操作系统释放内存。他们携手并进。