如何解决 Amazon RDS for MySQL 或 MariaDB 数据库中的低可用内​​存问题?

上次更新时间:2019 年 4 月 30 日

我在使用 Amazon Relational Database Service(Amazon RDS)MariaDB 或 MySQL 实例。我看到可用内存很低,数据库内存不足,或者内存不足导致应用程序出现延迟。如何识别什么在使用内存,以及如何解决低可用内存问题?

简短描述

MySQL 分配缓冲区和缓存来执行数据库操作。有关更多信息,请参阅 MySQL 文档中的 MySQL 如何使用内存部分。使用 Amazon RDS 时,实例上 80% 到 90% 的可用内存将使用默认参数进行分配。此分配对于性能而言是最佳的,但如果您设置使用更多内存的参数,则可修改其他参数以使用更少的内存来进行补偿。确定哪些组件正在使用内存后,您可以在实例和数据库级别查找瓶颈。然后,您可以配置会话以获得最佳性能。 

解决方法

了解 MySQL 如何使用内存

全局缓冲区和缓存包括 Innodb_buffer_pool_sizeInnodb_log_buffer_sizekey_buffer_size query_cache_size 等组件。默认情况下,innodb_buffer_pool_size 使用 RDS 数据库实例 75% 的内存。首先查看此参数以识别什么在使用内存。然后,考虑减少 innodb_buffer_pool_size 的值。例如,默认的 DBInstanceClassMemory*3/4 可以减少到 *5/8 *1/2。请务必检查实例的 BufferCacheHitRatio,以确保该比率不会太低。如果 BufferCacheHitRatio 很低,则可能需要增加实例大小,以便拥有更多 RAM。有关更多信息,请参阅为 Amazon RDS for MySQL 配置参数的最佳实践,第 1 部分:与性能相关的参数

内存也分配给连接到 MySQL 数据库实例的每个 MySQL 线程。以下线程需要分配的内存:

  • thread_stack
  • net_buffer_length
  • read_buffer_size
  • sort_buffer_size
  • join_buffer_size
  • max_heap_table_size
  • tmp_table_size

此外,MySQL 创建内部临时表以执行某些操作。这些表最初作为基于内存的表创建。当这些表的大小达到 tmp_table_size max_heap_table_size中指定的值(以较低者为准)时,则表将转换为基于磁盘的表。当多个会话创建内部临时表时,您可能会看到内存利用率上升。要降低内存利用率,请避免在查询中使用临时表。

如果在会话执行 JOINSORT 时分配了多个相同类型的缓冲区(例如 join_buffer_size sort_buffer_size),您也会看到内存使用率上升。例如,MySQL 分配一个 JOIN 缓冲区以在两个表之间执行 JOIN。如果查询涉及多个表 JOINs,并且所有查询都需要 JOIN 缓冲区,那么 MySQL 分配的 JOIN 缓冲区数量会比表的总数少一个。如果未优化查询,则使用过高的值配置会话变量可能会导致问题。您可以将最小内存分配给会话级变量,例如 join_buffer_size sort_buffer_size。有关更多信息,请参阅使用数据库参数组

如果对 MYISAM 表执行批量插入,则使用 bulk_insert_buffer_size 个字节的内存。有关更多信息,请参阅 MySQL 存储引擎使用最佳实践

如果您为 Amazon RDS for MySQL 上的 Performance Insights 启用了性能架构,那么性能架构会消耗内存。启用性能架构后,MySQL 会在实例启动时和服务器操作期间分配内部缓冲区。有关性能架构如何使用内存的更多信息,请参阅 MySQL 文档中的性能架构内存分配模型

监控和排除实例上的内存利用率问题

当可用内存不足时,监控 Amazon CloudWatch 指标 DatabaseConnectionsCPUUtilizationReadIOPSWriteIOPS。要检查内存压力,除 FreeableMemory 之外,监控 CloudWatch 指标 SwapUsage。如果您发现使用了大量的交换区并且 FreeableMemory 的值低,那么数据库实例可能正面临内存压力,这可能会导致性能下降。有关更多信息,请参阅在内存足够时,为什么我的 Amazon RDS 实例会使用交换内存?

要监控数据库实例上的资源利用率,请参阅启用增强监测。然后,将粒度设置为一到五秒(默认值为 60 秒)。

运行 SHOW FULL PROCESSLIST; 以查看所有打开的连接。然后,运行 SHOW ENGINE INNODB STATUS; 以查看 InnoDB 信息,例如长时间运行的事务、内存利用率统计数据和锁。查看 BUFFER POOL AND MEMORY 部分以了解是否有任何可用页。

最后,启用 Performance Insights,以识别消耗内存的查询。然后,对 FreeableMemory 指标设置 CloudWatch 警报,以便在可用内存减少时收到通知。最佳实践是保留至少 5% 的实例内存空闲,因此设置在达到 95% 的利用率时通知您的 CloudWatch 警报。

您可以使用性能架构内存表来监测内存利用率。您还可以使用 MySQL sys schema 来简化视图,以与性能架构表结合使用。例如,您可以使用 performance_schema 事件来显示为性能架构使用的内部缓冲区分配的内存量。或者,您可以运行类似于以下内容的查询,以查看分配了多少内存:

SELECT * FROM performance_schema.memory_summary_global_by_event_name WHERE EVENT_NAME LIKE 'memory/performance_schema/%';

内存工具在 setup_instruments 表中列出。这些工具的名称基于 memory/code_area/instrument_name,例如 memory/innodb/buf_buf_pool。要启用内存检测,请更新 setup_instruments 表中相关工具的 ENABLED 列:

UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'memory/%';

这篇文章对您有帮助吗?

您觉得我们哪些地方需要改进?


需要更多帮助?