我在运行一个 Amazon Relational Database Service(Amazon RDS)数据库实例。尽管我分配了足够的可用内存,但它仍在使用大量的虚拟内存。为什么尽管内存足够,系统仍在使用虚拟内存?
简短描述
当系统需要的内存多于分配的内存时,运行 Linux 的 Amazon Elastic Compute Cloud (Amazon EC2) 实例会使用交换内存。有关更多信息,请参阅实例存储交换卷。由于大多数 RDS 数据库实例使用 Linux(SQL Server 除外),因此数据库有时会使用虚拟内存。
仅当页面正被访问时,RDS 数据库实例才需要 RAM 中的页面,例如在运行查询时。如果最近未使用过,则由先前运行的查询带入 RAM 的其他页面将被刷新到虚拟内存空间。最佳实践是让操作系统(OS)交换旧的页而不是强制操作系统将页保留在内存中。这可确保有足够的可用 RAM 用于未来的查询。
Linux 使用的虚拟内存不会经常清除,因为在清除使用的虚拟内存时,需要额外的开销来在需要时和重新加载页时重新分配虚拟内存。因此,如果 RDS 数据库实例使用了虚拟内存空间,即使仅使用过一次,SwapUsage 指标也不会归零。如果您使用 Amazon RDS for Oracle 支持的 HugePage 以及 Amazon RDS for PostgreSQL 上的 HugePage,那么也会消耗虚拟内存。HugePage 大于 Linux 默认的 2 兆字节大小。
解决方法
要了解 RDS 数据库实例的交换内存使用行为,请首先根据应用程序工作负载检查数据库性能指标。检查 Amazon CloudWatch 指标 FreeableMemory 和 SwapUsage,以了解 RDS 数据库实例的整体内存使用模式。检查这些指标,留意 SwapUsage 指标上升的同时 FreeableMemory 指标减少的情况。这可以表明 RDS 数据库实例在内存方面面临压力。有关更多信息,请参阅如何解决 Amazon RDS for MySQL 数据库中可用内存低的问题? 如果有足够的可用内存,则虚拟内存的使用应该不会影响 RDS 数据库实例的性能。如果可用内存始终处于较低水平,则可以更改 RDS 数据库实例大小以使其拥有更多内存的实例大小。
要监测交换内存,请开启增强监测,以最短为一秒的时间间隔检查指标。增强监控会采集主机级别的统计数据,CloudWatch 会每 60 秒采集管理程序级别的数据。您可以使用增强监控来识别仅发生一秒钟的增加或减少,并查看各个进程使用的 CPU 和内存。有关更多信息,请参阅使用 CloudWatch Logs 查看操作系统指标。
您还可以开启 Performance Insights 来识别在 RDS 数据库实例上消耗过多虚拟内存或内存的 SQL 事件和等待事件。Performance Insights 采集数据库级别的数据,并在 Performance Insights 控制面板中显示数据。Performance Insights 可以帮助排查与数据库性能相关的问题。有关更多信息,请参阅使用 Amazon RDS 上的 Performance Insights 监控数据库负载。
Amazon RDS for MySQL
如果可用内存较低,可运行 SHOW FULL PROCESSLIST 来检查在数据库上运行的所有线程。来自 SHOW FULL PROCESSLIST 输出的进程 ID 与增强监控中显示的进程 ID 不一致。要查看正确的进程 ID,请将与数据库关联的数据库参数组修改为 Performance_Schema 参数。这是一个静态参数,因此您必须重新启动 RDS 数据库实例。为避免停机,请在非流量高峰时间修改参数并重新启动数据库。在内存达到想要的利用率时,请遵循以下步骤:
1. 在“增强监测”页面中对进程 ID 进行排序,以查看 CPU 占用最多的进程的 ID。
2. 以主用户身份运行以下查询:
select * from performance_schema.threads where THREAD_OS_ID in (ID shown in the Enhanced Monitoring window)\G
例如,假设 Thread_OS_Id 10374 和 1432 使用了最多的内存,则运行以下查询:
select * from performance_schema.threads where THREAD_OS_ID in (10374, 1432)\G
有关更多信息,请参阅 MySQL 网站上的线程表。
3. 从此查询的输出中获取 PROCESSLIST_ID 列。这为您提供了与 SHOW FULL PROCESSLIST 中的进程 ID 值相匹配的进程 ID。
拥有正确的进程 ID 后,您可以将进程 ID 映射到查询。您可以使用该 ID 来确定造成高内存和 CPU 利用率的根本原因。您可以使用增强监测查看操作系统进程。有关更多信息,请参阅在 RDS 控制台中查看操作系统指标。
Amazon RDS for PostgreSQL
要识别消耗大量内存的进程,请将增强监控进程列表中的进程 ID 映射到确切的查询。要标识该进程,请运行以下 pg_stat_activity 视图:
select * from pg_stat_activity where pid=(the PID of your process);
然后,调整查询使其消耗更少的计算资源。
Amazon RDS for SQL Server
增强监控可以识别消耗大量内存的特定线程 ID。线程 ID 就是 SQL Server 中的内核进程 ID(KPID)。
从 Amazon RDS for SQL Server,运行以下查询以获取与 KPID 对应的服务器进程 ID (SPID):
select * from sys.sysprocesses where kpid = '<Value of Thread ID from Enhanced Monitoring>' ;
获得服务器进程 ID 后,例如进程 ID 是 69,运行以下命令来查看 SPID 69 正在运行的内容:
dbcc inputbuffer(69)
Amazon RDS for Oracle
通过使用增强监控中的操作系统进程 ID,您可以查看哪个进程消耗的内存最多。然后,运行以下查询以获取会话的进程地址:
select ADDR from v$process where SPID=OS_PID;
您可以运行以下查询来使用进程地址识别数据库中的会话:
select sid,serial#,username, status from v$session where PADDR='<ADDR from above query>';
相关信息
监控 Amazon RDS 概述