Amazon RDS for MySQL 또는 MariaDB 데이터베이스의 여유 메모리 수준이 낮은 문제를 해결하려면 어떻게 해야 합니까?

최종 업데이트 날짜: 2019년 4월 30일

Amazon RDS(Amazon Relational Database Service) MariaDB 또는 MySQL 인스턴스를 실행 중입니다. 사용 가능한 메모리 수준이 낮거나, 데이터베이스의 메모리가 부족하거나, 메모리 부족으로 인해 애플리케이션에 지연 시간 문제가 발생하는 것을 볼 수 있습니다. 메모리 사용의 출처를 식별하고 여유 메모리 수준이 낮은 문제를 해결하려면 어떻게 해야 합니까?

간략한 설명

MySQL은 데이터베이스 작업 을 수행하기 위해 버퍼와 캐시를 할당합니다. 자세한 내용은 MySQL 설명서의 How MySQL Uses Memory를 참조하십시오. Amazon RDS를 사용할 때, 인스턴스에서 사용 가능한 메모리의 80%~90%가 기본 파라미터를 사용하여 할당됩니다. 이 할당은 성능에 최적화되어 있지만 더 많은 메모리를 사용하는 파라미터를 설정하는 경우에는 이를 보상하도록 더 적은 메모리를 사용하는 다른 파라미터를 설정합니다. 어떤 구성 요소가 메모리를 사용하는지 식별했으면 인스턴스 및 데이터베이스 수준의 병목 현상을 찾을 수 있습니다. 그런 다음, 최적의 성능을 위해 세션을 구성할 수 있습니다. 

​해결 방법

MySQL 메모리를 사용하는 방법 이해

글로벌 버퍼와 캐시는 Innodb_buffer_pool_size, Innodb_log_buffer_size, key_buffer_sizequery_cache_size 같은 구성 요소를 포함합니다. 기본적으로 innodb_buffer_pool_size는 RDS DB 인스턴스의 메모리 중 75%를 사용합니다. 이 파라미터를 먼저 검토하여 메모리 사용 출처를 식별합니다. 그런 다음, innodb_buffer_pool_size 값을 줄이는 것을 고려합니다. 예를 들어 기본값인 DBInstanceClassMemory*3/4*5/8 또는 *1/2로 줄일 수 있습니다. 인스턴스의 BufferCacheHitRatio를 확인하여 비율이 너무 낮지 않게 합니다. BufferCacheHitRatio가 낮은 경우 더 많은 RAM을 가질 수 있도록 인스턴스 크기를 늘려야 할 수 있습니다. 자세한 내용은 Best practices for configuring parameters for Amazon RDS for MySQL, part 1: Parameters related to performance를 참조하십시오.

메모리는 MySQL DB 인스턴스에 연결된 각 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에 의해 지정된 값(둘 중 가장 낮은 값 적용)에 도달하면 테이블이 디스크 기반 테이블로 변환됩니다. 여러 세션이 내부 임시 테이블을 생성할 때 메모리 사용률이 증가하는 것을 볼 수도 있습니다. 메모리 사용률을 줄이려면 쿼리에 임시 테이블을 사용하지 않도록 합니다.

또한, 세션이 JOIN 또는 SORT 작업을 수행할 때 join_buffer_size 또는 sort_buffer_size와 같은 동일한 유형의 버퍼가 여러 개 할당된 경우에도 메모리 사용량이 증가하는 것을 볼 수 있습니다. 예를 들어, MySQL은 두 테이블 사이에 JOIN을 수행하기 위해 하나의 JOIN 버퍼를 할당합니다. 쿼리에 다중 테이블 JOIN이 수반되며 모든 쿼리에 JOIN 버퍼가 필요한 경우, MySQL은 총 테이블 수보다 한 개 더 적은 JOIN 버퍼를 할당합니다. 너무 높은 값으로 세션 변수를 구성하면 쿼리가 최적화되지 않은 경우 문제를 유발할 수 있습니다. join_buffer_sizesort_buffer_size와 같은 세션 수준 변수에 최소 메모리를 할당할 수 있습니다. 자세한 내용은 DB 파라미터 그룹 작업을 참조하십시오.

MYISAM 테이블에 대량 삽입을 수행하는 경우에는 bulk_insert_buffer_size 바이트의 메모리가 사용됩니다. 자세한 내용은 MySQL 스토리지 엔진으로 작업하기 위한 모범 사례를 참조하십시오.

Amazon RDS for MySQL에 대한 성능 개선 도우미를 위해 성능 스키마를 활성화한 경우 성능 스키마에 의해 메모리가 소비될 수 있습니다. 성능 스키마가 활성화된 경우, MySQL은 인스턴스를 시작할 때 및 서버 작업을 수행하는 동안 내부 버퍼를 할당합니다. 성능 스키마가 메모리를 사용하는 방식에 대한 자세한 내용은 MySQL 설명서의 The Performance Schema Memory-Allocation Model을 참조하십시오.

인스턴스에서의 메모리 사용량 모니터링 및 문제 해결

사용 가능한 메모리 수준이 낮으면 DatabaseConnections, CPUUtilization, ReadIOPSWriteIOPS에 대한 Amazon CloudWatch 측정치를 모니터링합니다. 메모리 압력을 확인하려면 FreeableMemory뿐 아니라 SwapUsage에 대한 CloudWatch 측정치를 모니터링합니다. 많은 양의 스왑이 사용되는 것이 보이는 경우 FreeableMemory 수준이 낮은 것이며 DB 인스턴스에 성능을 저하시키는 메모리 압력이 발생하고 있는 것일 수 있습니다. 자세한 내용은 왜 내 Amazon RDS 인스턴스는 충분한 메모리가 있는 데에도 스왑 메모리를 사용합니까?를 참조하십시오.

DB 인스턴스 리소스 사용량을 모니터링하려면 Enhanced Monitoring을 활성화합니다. 그런 다음 1초에서 5초 사이의 세부 수준을 설정합니다(기본값은 60초).

SHOW FULL PROCESSLIST;를 실행하여 모든 연결을 봅니다. 그런 다음, SHOW ENGINE INNODB STATUS;를 실행하여 InnoDB 정보(예: 장기 실행 트랜잭션, 메모리 사용률 통계 및 잠금)를 봅니다. [BUFFER POOL AND MEMORY] 섹션을 검토하여 여유 페이지가 있는지 확인합니다.

마지막으로, 메모리를 소비하는 쿼리를 식별할 수 있도록 성능 개선 도우미를 활성화합니다. 그런 다음, 사용 가능한 메모리가 감소할 때 알림을 수신하도록 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/innodb/buf_buf_pool과 같이 memory/code_area/instrument_name에 기반한 이름을 가지고 있습니다. 메모리 계측을 활성화하려면 setup_instruments 테이블에서 관련 계측 장치의 ENABLED 열을 업데이트합니다.

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

이 문서가 도움이 되었습니까?

AWS에서 개선해야 할 부분이 있습니까?


도움이 필요하십니까?