AWS Builder Center: Learn, Build and Connect with builders in the AWS community
AWS Builder Center is the official home for builders on AWS. Share and read what others are working on, follow people who inspire you, explore training and workshops, and find tools to support what you're building.
如何对 Amazon RDS for MySQL 数据库中可用内存不足的问题进行故障排除?
我想对运行 Amazon Relational Database Service (Amazon RDS) for MySQL 实例时出现的内存不足问题进行故障排除。我的可用内存不足,数据库内存不足,或者应用程序出现延迟问题。
解决方法
重要事项:性能详情将于 2026 年 6 月 30 日到期。您可以在 2026 年 6 月 30 日之前升级到数据库洞察的高级模式。如果您不进行升级,则使用性能详情的数据库集群将默认采用数据库洞察的标准模式。只有数据库洞察的高级模式才支持执行计划和按需分析。如果您的集群默认采用标准模式,则您可能无法在控制台上使用这些功能。要开启高级模式,请参阅开启适用于 Amazon RDS 的数据库洞察的高级模式和开启适用于 Amazon Aurora 的数据库洞察的高级模式。
提高数据库性能
要提高数据库性能,请优化和调整查询。使用 Amazon RDS 性能详情来监控数据库实例并识别存在问题的查询。然后,在 FreeableMemory 指标上设置 Amazon CloudWatch 警报,这样当可用内存已经使用了 95% 时,您就会收到通知。最佳实践是保持至少 5% 的实例内存处于空闲状态。
检查 Amazon RDS for MySQL 中的内存分配
计算您的内存分配
要计算您的数据库实例的大致内存使用量,请使用以下公式:
总内存使用量 = (innodb_additional_mem_pool_size + innodb_buffer_pool_size + innodb_log_buffer_size + key_buffer_size + query_cache_size + tmp_table_size) + max_connections (binlog_cache_size + join_buffer_size + read_buffer_size + read_rnd_buffer_size + sort_buffer_size + thread_stack ) + (performance_schema max_connections * 429498)`
确保为数据库分配了足够的资源来运行查询。某些查询(例如存储过程)在运行时可能会无限制地占用内存。为避免长时间运行的事务,请将大型查询分成较小的查询。有关 Amazon RDS for MySQL 如何使用内存的更多信息,请参阅 MySQL 网站上的 How MySQL Uses Memory(MySQL 如何使用内存)。
最佳做法是定期升级实例的 MySQL 次要版本。早期的次要版本可能包含与内存泄漏相关的错误。有关 MySQL 版本的更多信息,请参阅 MySQL 网站上的 MySQL 8.0 release notes(MySQL 8.0 发行说明)。
检查您的缓冲池大小
要查看长时间运行的事务、内存利用率统计数据或锁定,请使用 SHOW ENGINE INNODB STATUS 命令。有关 SHOW ENGINE 查询的更多信息,请参阅 MySQL 网站上的 SHOW ENGINE query(SHOW ENGINE 查询)。查看输出并检查 BUFFER POOL AND MEMORY 条目以了解有关 InnoDB 内存分配的信息,例如 Total Memory Allocated、Internal Hash Tables 和 Buffer Pool Size。如果您的工作负载经常遇到死锁,请修改自定义参数组中的 innodb_lock_wait_timeout 参数。发生死锁时,InnoDB 依赖 innodb_lock_wait_timeout 设置来回滚事务。
较大的缓冲池可以减少转移回磁盘的 I/O 操作。默认情况下,innodb_buffer_pool_size 最多使用分配给 Amazon RDS 数据库实例的 75% 的可用内存:innodb_buffer_pool_size = DBInstanceClassMemory*3/4。有关缓冲池的更多信息,请参阅 MySQL 网站上的 Buffer Pool(缓冲池)。
要确定内存使用来源,请检查 innodb_buffer_pool_size。然后,如果需要,修改自定义参数组中的参数值以减少 innodb_buffer_pool_size。
有关更多信息,请参阅为 Amazon RDS for MySQL 配置参数的最佳实践,第 1 部分: 与性能相关的参数。
检查您的 MySQL 线程
系统还会为连接到 MySQL 数据库实例的每个 MySQL 线程分配内存。有关需要分配内存的 MySQL 线程的更多信息,请参阅 MySQL 和 MariaDB 问题页面上的“诊断并解决内存限制的不兼容参数状态”。
MySQL 会创建临时内部表来执行某些操作。如果表达到 tmp_table_size 或 max_heap_table_size 的最低值,则 MySQL 会将表从基于内存的表转换为基于磁盘的表。如果多个会话创建临时内部表,则您可能会看到内存使用量增加。为了减少内存使用,请仅在查询中使用最大表。有关更多信息,请参阅 MySQL 网站上的 Server System Variables(服务器系统变量)和 MySQL 网站上的 How MySQL uses memory(MySQL 如何使用内存)。
如果您增加 tmp_table_size 和 max_heap_table_size 值,则可将更大的临时表存放内存中。要验证 MySQL 是否创建了隐式临时表,请使用 created_tmp_tables 变量。有关此变量的更多信息,请参阅 MySQL 网站上的 Created_tmp_tables。
查看活动的 JOIN 和 SORT 操作
如果您确定需要临时表的查询,则必须有额外的内存来分配给该表。要查看数据库中的活动连接和查询,请使用 SHOW FULL PROCESSLIST 命令。有关 SHOW FULL PROCESSLIST 和示例查询的更多信息,请参阅 MySQL 网站上的 SHOW PROCESSLIST query(SHOW PROCESSLIST 查询)。
在 JOIN 或 SORT 操作期间,如果 MySQL 分配多个相同类型的缓冲区,例如 join_buffer_size 或 sort_buffer_size,则内存使用量将会增加。例如,MySQL 分配一个 JOIN 缓冲区来执行两个表的 JOIN 操作。对于使用多个 JOIN 表且所有查询都需要 JOIN 缓冲区的查询,MySQL 分配的 JOIN 缓冲区比表总数少一个。
如果您使用过高的值配置会话变量,则可能会收到错误。要解决此错误,请为诸如 join_buffer_size 和 sort_buffer_size 等会话级变量分配所需的最小内存。
**注意:**如果您对 MYISAM 表执行批量插入,则 MySQL 会使用 bulk_insert_buffer_size 字节的内存。有关详细信息,请参阅使用 MySQL 的最佳实践。
激活性能架构
如果您开启性能详情,MySQL 会在您启动实例时和服务器操作期间为性能架构分配内部缓冲区。有关性能架构如何使用内存的更多信息,请参阅 MySQL 网站上的 The Performance Schema Memory-Allocation Model(性能架构内存分配模型)。
监控您的实例的内存使用量
检查您的 CloudWatch 指标
要检查内存是否不足,请使用 Aurora 和 RDS 控制台上的 Monitoring(监控)选项卡,监控 DatabaseConnections、CPUUtilization、ReadIOPS 和 WriteIOPS CloudWatch 指标。
对于DatabaseConnections,与数据库建立的每个连接都需要分配内存,这可能会减少可用内存。使用以下公式计算估计的最大 max_connections 配额:DBInstanceClassMemory/12582880
要检查您是否已超过 max_connections 配额,请检查 DatabaseConnections CloudWatch 指标。
要检查内存压力,请监控 SwapUsage 和 FreeableMemory CloudWatch 指标。最佳做法是将内存压力水平保持在 95% 以下,从而提高数据库性能。有关详细信息,请参阅为什么尽管内存足够,我的 Amazon RDS 数据库实例仍在使用交换内存?
使用 MySQL sys 架构跟踪内存使用情况
使用 MySQL sys 架构来跟踪连接、组件以及内存查询。有关更多信息,请参阅 MySQL 网站上的 Chapter 30 MySQL sys schema(第 30 章 MySQL sys 架构)。使用 MySQL sys 架构和性能架构表来识别并跟踪当前的内存使用情况。
**注意:**必须激活性能架构才能使用 sys 架构。
要跟踪 sys 架构中的内存使用情况,请登录数据库并执行以下操作:
- 使用 memory_by_host_by_current_bytes 来确定哪个主机使用的内存最多。
- 使用 memory_by_thread_by_current_bytes 来确定哪个线程 ID 使用的内存最多。
**注意:**MySQL 中的线程 ID 可以是客户端连接或后台线程。您可以使用 sys.processlist 视图或 performance_schema.threads 表,将线程 ID 映射到 MySQL 连接 ID。 - 使用 memory_by_user_by_current_bytes 来确定哪个用户使用的内存最多。
- 使用 memory_global_by_current_bytes 来确定哪个引擎组件使用的内存最多。
- 使用 memory_global_total 来查看数据库引擎中跟踪到的内存总使用量。
- 使用 sys.memory_global_by_current_bytes 来确定哪个组件使用的内存最多。
**注意:**对于与性能架构相关的内存事件,请使用 memory/performance_schema/%。对于 InnoDB,请使用 memory/innodb/%。
要确定哪些功能组件在全局级别耗用的内存最多,请运行以下查询:
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(event_name, '/', 2), '/', -1 ) AS event_type, ROUND(SUM(CURRENT_NUMBER_OF_BYTES_USED)/1024/1024, 2) AS MB_CURRENTLY_USED FROM performance_schema.memory_summary_global_by_event_name GROUP BY event_type HAVING MB_CURRENTLY_USED>0;
如果 performance_schema 使用的内存最多,则运行以下查询确定占用内存的 event_name。
select * from sys.memory_global_by_current_bytes where event_name like '%performance_schema%' and current_count > 0;
select * from performance_schema.memory_summary_global_by_event_name WHERE EVENT_NAME LIKE 'memory/performance_schema/%'order by CURRENT_NUMBER_OF_BYTES_USED desc;
然后,运行以下查询:
select * from sys.memory_global_by_current_bytes where event_name like 'memory/sql%' and current_count > 0;
select p.id,p.user,p.host,p.db,p.command,p.state,p.info,t.thread_id,t.type from information_schema.processlist p, performance_schema.threads t where p.id=t.processlist_id and t.thread_id=thread_id;
**注意:**将 memory/sql% 替换为您的事件类型。
要查看特定线程每个事件的内存分配详细信息,请运行以下查询:
select * from performance_schema.memory_summary_by_thread_by_event_name where thread_id=thread_id and CURRENT_COUNT_USED >0 order by CURRENT_NUMBER_OF_BYTES_USED desc;
您可以使用 performance_schema 事件来显示 MySQL 为性能架构使用的内部缓冲区分配了多少内存。要查看分配了多少内存,请运行以下查询:
select * from performance_schema.memory_summary_global_by_event_name WHERE EVENT_NAME LIKE 'memory/performance_schema/%';
您可以在 setup_instruments 表中以 memory/code_area/instrument_name 格式查找内存工具。
要在性能架构中启用内存检测,请在 performance_schema.setup_instruments 表中将工具的 ENABLED 列设置为 YES。
**注意:**在 MySQL 8.x 中,当性能架构处于活动状态时,内存检测默认也处于活动状态。
监控资源使用情况
要监控数据库实例的资源使用情况,请激活增强监控。然后,将粒度设置为 1 到 5 秒之间。默认粒度为 60 秒。您可以使用增强监控来实时查看可用内存和活动内存。
要监控耗用最多 CPU 和内存的线程,请运行以下命令列出数据库实例的线程:
select THREAD_ID, PROCESSLIST_ID, THREAD_OS_ID from performance_schema.threads;
然后,运行以下命令将 thread_OS_ID 映射到 thread_ID:
select p.* from information_schema.processlist p, performance_schema.threads t where p.id=t.processlist_id and t.thread_os_id=thread-ID;
**注意:**将 thread-ID 替换为线程 ID。

