Aurora MySQL 데이터베이스의 메모리 사용량 문제 해결 - Amazon Aurora

Aurora MySQL 데이터베이스의 메모리 사용량 문제 해결

CloudWatch, 향상된 모니터링 및 성능 개선 도우미는 운영 체제 수준에서 데이터베이스 프로세스에서 사용하는 메모리 양 등의 메모리 사용량에 대한 유용한 개요를 제공하지만, 이러한 메모리 사용량을 유발할 수 있는 엔진 내 연결 또는 구성 요소를 분석할 수는 없습니다.

이 문제를 해결하기 위해 성능 스키마와 sys 스키마를 사용할 수 있습니다. Aurora MySQL 버전 3에서 메모리 계측은 성능 스키마가 사용 설정되면 기본적으로 활성화됩니다. Aurora MySQL 버전 2에서는 성능 스키마 메모리 사용량의 메모리 계측만 기본적으로 사용 설정됩니다. 성능 스키마에서 메모리 사용량을 추적하고 성능 스키마 메모리 계측을 사용 설정하는 데 사용할 수 있는 테이블에 대한 자세한 내용은 MySQL 설명서의 메모리 요약 테이블을 참조하시기 바랍니다. 성능 개선 도우미에서 성능 스키마를 사용하는 것에 대한 자세한 내용은 Aurora MySQL에서 성능 개선 도우미의 성능 스키마 개요 섹션을 참조하세요.

성능 스키마에서 현재 메모리 사용량을 추적할 수 있는 자세한 정보가 나와 있지만, MySQL 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

엔진 구성 요소별 엔진 메모리 사용량에 대한 정보를 제공합니다. 이 정보를 통해 엔진 버퍼 또는 구성 요소별 메모리 사용량을 전체적으로 식별할 수 있습니다. 예를 들어 InnoDB 버퍼 풀의 memory/innodb/buf_buf_pool 이벤트 또는 준비된 문에 대한 memory/sql/Prepared_statement::main_mem_root 이벤트를 볼 수 있습니다.

memory_global_total

데이터베이스 엔진에서 추적된 총 메모리 사용량에 대한 개요를 제공합니다.

Aurora MySQL 버전 3.05 이상에서는 성능 스키마 문 요약 테이블에서 문 다이제스트를 통해 최대 메모리 사용량을 추적할 수도 있습니다. 문 요약 테이블에는 정규화된 문 요약과 실행에 대한 집계된 통계가 포함되어 있습니다. 이 MAX_TOTAL_MEMORY 열을 통해 통계가 마지막으로 재설정된 이후 또는 데이터베이스 인스턴스가 재시작된 이후 쿼리 다이제스트에서 사용된 최대 메모리를 식별할 수 있습니다. 이를 통해 메모리를 많이 사용할 수 있는 특정 쿼리를 식별할 수 있습니다.

참고

성능 스키마와 sys 스키마는 서버의 현재 메모리 사용량과 연결 및 엔진 구성 요소당 사용된 메모리의 상한선을 보여줍니다. 성능 스키마는 메모리에 유지 관리되므로 DB 인스턴스가 다시 시작될 때 정보가 재설정됩니다. 시간이 지나도 기록을 계속해서 유지하려면 성능 스키마 외부에서 이 데이터를 검색 및 저장하도록 구성하는 것이 좋습니다.

예제 1: 지속적인 높은 메모리 사용량

전반적으로 CloudWatch에서 FreeableMemory를 살펴보면 2024-03-26 02:59 UTC를 기준으로 메모리 사용량이 크게 증가한 것을 확인할 수 있습니다.

높은 메모리 사용량을 보여주는 FreeableMemory 그래프입니다.

이것이 전부는 아닙니다. 어떤 구성 요소가 메모리를 가장 많이 사용하고 있는지 확인하려면 데이터베이스에 로그인하여 sys.memory_global_by_current_bytes를 살펴보시기 바랍니다. 이 표에는 MySQL이 추적하는 메모리 이벤트 목록과 이벤트별 메모리 할당 정보가 포함되어 있습니다. 각 메모리 추적 이벤트는 memory/%로 시작되며 이벤트와 관련된 엔진 구성 요소/특성에 대한 기타 정보가 뒤따릅니다.

예를 들어 memory/performance_schema/%는 성능 스키마와 관련된 메모리 이벤트용이고 memory/innodb/%는 InnoDB용 등입니다. 이벤트 이름 지정 규칙에 대한 자세한 내용은 MySQL 설명서의 성능 스키마 계측 이름 지정 규칙을 참조하세요.

다음 쿼리에서는 current_alloc을 기반으로 유력한 원인을 찾을 수 있지만 많은 memory/performance_schema/% 이벤트도 확인할 수 있습니다.

mysql> SELECT * FROM sys.memory_global_by_current_bytes LIMIT 10; +-----------------------------------------------------------------------------+---------------+---------------+-------------------+------------+------------+----------------+ | event_name | current_count | current_alloc | current_avg_alloc | high_count | high_alloc | high_avg_alloc | +-----------------------------------------------------------------------------+---------------+---------------+-------------------+------------+------------+----------------+ | memory/sql/Prepared_statement::main_mem_root | 512817 | 4.91 GiB | 10.04 KiB | 512823 | 4.91 GiB | 10.04 KiB | | memory/performance_schema/prepared_statements_instances | 252 | 488.25 MiB | 1.94 MiB | 252 | 488.25 MiB | 1.94 MiB | | memory/innodb/hash0hash | 4 | 79.07 MiB | 19.77 MiB | 4 | 79.07 MiB | 19.77 MiB | | memory/performance_schema/events_errors_summary_by_thread_by_error | 1028 | 52.27 MiB | 52.06 KiB | 1028 | 52.27 MiB | 52.06 KiB | | memory/performance_schema/events_statements_summary_by_thread_by_event_name | 4 | 47.25 MiB | 11.81 MiB | 4 | 47.25 MiB | 11.81 MiB | | memory/performance_schema/events_statements_summary_by_digest | 1 | 40.28 MiB | 40.28 MiB | 1 | 40.28 MiB | 40.28 MiB | | memory/performance_schema/memory_summary_by_thread_by_event_name | 4 | 31.64 MiB | 7.91 MiB | 4 | 31.64 MiB | 7.91 MiB | | memory/innodb/memory | 15227 | 27.44 MiB | 1.85 KiB | 20619 | 33.33 MiB | 1.66 KiB | | memory/sql/String::value | 74411 | 21.85 MiB | 307 bytes | 76867 | 25.54 MiB | 348 bytes | | memory/sql/TABLE | 8381 | 21.03 MiB | 2.57 KiB | 8381 | 21.03 MiB | 2.57 KiB | +-----------------------------------------------------------------------------+---------------+---------------+-------------------+------------+------------+----------------+ 10 rows in set (0.02 sec)

앞서 설명했듯이 성능 스키마는 메모리에 저장됩니다. 즉, performance_schema 메모리 계측에서 추적할 수도 있습니다.

참고

성능 스키마가 메모리를 많이 사용하고 있고 메모리 사용량을 제한하려는 경우 요구 사항에 따라 데이터베이스 파라미터를 조정할 수 있습니다. 자세한 내용은 MySQL 설명서의 성능 스키마 메모리 할당 모델을 참조하세요.

가독성을 위해 동일한 쿼리를 다시 실행하되 성능 스키마 이벤트는 제외할 수 있습니다. 출력은 다음과 같이 표시됩니다.

  • memory/sql/Prepared_statement::main_mem_root에서 주로 메모리가 사용됩니다.

  • current_alloc 열에는 MySQL이 현재 이 이벤트에 4.91GiB를 할당하고 있음이 나와 있습니다.

  • high_alloc column에는 통계가 마지막으로 재설정된 이후 또는 서버가 다시 시작된 이후 4.91GiB가 최고 current_alloc 수치임이 나와 있습니다. 즉, memory/sql/Prepared_statement::main_mem_root가 현재 해당 최대치에 있다는 의미입니다.

mysql> SELECT * FROM sys.memory_global_by_current_bytes WHERE event_name NOT LIKE 'memory/performance_schema/%' LIMIT 10; +-----------------------------------------------+---------------+---------------+-------------------+------------+------------+----------------+ | event_name | current_count | current_alloc | current_avg_alloc | high_count | high_alloc | high_avg_alloc | +-----------------------------------------------+---------------+---------------+-------------------+------------+------------+----------------+ | memory/sql/Prepared_statement::main_mem_root | 512817 | 4.91 GiB | 10.04 KiB | 512823 | 4.91 GiB | 10.04 KiB | | memory/innodb/hash0hash | 4 | 79.07 MiB | 19.77 MiB | 4 | 79.07 MiB | 19.77 MiB | | memory/innodb/memory | 17096 | 31.68 MiB | 1.90 KiB | 22498 | 37.60 MiB | 1.71 KiB | | memory/sql/String::value | 122277 | 27.94 MiB | 239 bytes | 124699 | 29.47 MiB | 247 bytes | | memory/sql/TABLE | 9927 | 24.67 MiB | 2.55 KiB | 9929 | 24.68 MiB | 2.55 KiB | | memory/innodb/lock0lock | 8888 | 19.71 MiB | 2.27 KiB | 8888 | 19.71 MiB | 2.27 KiB | | memory/sql/Prepared_statement::infrastructure | 257623 | 16.24 MiB | 66 bytes | 257631 | 16.24 MiB | 66 bytes | | memory/mysys/KEY_CACHE | 3 | 16.00 MiB | 5.33 MiB | 3 | 16.00 MiB | 5.33 MiB | | memory/innodb/sync0arr | 3 | 7.03 MiB | 2.34 MiB | 3 | 7.03 MiB | 2.34 MiB | | memory/sql/THD::main_mem_root | 815 | 6.56 MiB | 8.24 KiB | 849 | 7.19 MiB | 8.67 KiB | +-----------------------------------------------+---------------+---------------+-------------------+------------+------------+----------------+ 10 rows in set (0.06 sec)

이벤트 이름을 보면 이 메모리가 준비된 문에 사용되고 있음을 알 수 있습니다. 어떤 연결이 이 메모리를 사용하고 있는지 알아보려면 memory_by_thread_by_current_bytes를 확인하시기 바랍니다.

다음 예제에서 각 연결에는 약 7MiB가 할당되어 있으며 최고 수치는 약 6.29MiB(current_max_alloc)입니다. 이 예제에서는 준비된 문을 포함하는 80개의 테이블과 800개의 연결을 가진 sysbench를 사용하고 있으므로 납득 가능한 수치입니다. 이 시나리오에서 메모리 사용량을 줄이려면 준비된 문의 애플리케이션 사용량을 최적화하여 메모리 사용량을 줄일 수 있습니다.

mysql> SELECT * FROM sys.memory_by_thread_by_current_bytes; +-----------+-------------------------------------------+--------------------+-------------------+-------------------+-------------------+-----------------+ | thread_id | user | current_count_used | current_allocated | current_avg_alloc | current_max_alloc | total_allocated | +-----------+-------------------------------------------+--------------------+-------------------+-------------------+-------------------+-----------------+ | 46 | rdsadmin@localhost | 405 | 8.47 MiB | 21.42 KiB | 8.00 MiB | 155.86 MiB | | 61 | reinvent@10.0.4.4 | 1749 | 6.72 MiB | 3.93 KiB | 6.29 MiB | 14.24 MiB | | 101 | reinvent@10.0.4.4 | 1845 | 6.71 MiB | 3.72 KiB | 6.29 MiB | 14.50 MiB | | 55 | reinvent@10.0.4.4 | 1674 | 6.68 MiB | 4.09 KiB | 6.29 MiB | 14.13 MiB | | 57 | reinvent@10.0.4.4 | 1416 | 6.66 MiB | 4.82 KiB | 6.29 MiB | 13.52 MiB | | 112 | reinvent@10.0.4.4 | 1759 | 6.66 MiB | 3.88 KiB | 6.29 MiB | 14.17 MiB | | 66 | reinvent@10.0.4.4 | 1428 | 6.64 MiB | 4.76 KiB | 6.29 MiB | 13.47 MiB | | 75 | reinvent@10.0.4.4 | 1389 | 6.62 MiB | 4.88 KiB | 6.29 MiB | 13.40 MiB | | 116 | reinvent@10.0.4.4 | 1333 | 6.61 MiB | 5.08 KiB | 6.29 MiB | 13.21 MiB | | 90 | reinvent@10.0.4.4 | 1448 | 6.59 MiB | 4.66 KiB | 6.29 MiB | 13.58 MiB | | 98 | reinvent@10.0.4.4 | 1440 | 6.57 MiB | 4.67 KiB | 6.29 MiB | 13.52 MiB | | 94 | reinvent@10.0.4.4 | 1433 | 6.57 MiB | 4.69 KiB | 6.29 MiB | 13.49 MiB | | 62 | reinvent@10.0.4.4 | 1323 | 6.55 MiB | 5.07 KiB | 6.29 MiB | 13.48 MiB | | 87 | reinvent@10.0.4.4 | 1323 | 6.55 MiB | 5.07 KiB | 6.29 MiB | 13.25 MiB | | 99 | reinvent@10.0.4.4 | 1346 | 6.54 MiB | 4.98 KiB | 6.29 MiB | 13.24 MiB | | 105 | reinvent@10.0.4.4 | 1347 | 6.54 MiB | 4.97 KiB | 6.29 MiB | 13.34 MiB | | 73 | reinvent@10.0.4.4 | 1335 | 6.54 MiB | 5.02 KiB | 6.29 MiB | 13.23 MiB | | 54 | reinvent@10.0.4.4 | 1510 | 6.53 MiB | 4.43 KiB | 6.29 MiB | 13.49 MiB | . . . . . . | 812 | reinvent@10.0.4.4 | 1259 | 6.38 MiB | 5.19 KiB | 6.29 MiB | 13.05 MiB | | 214 | reinvent@10.0.4.4 | 1279 | 6.38 MiB | 5.10 KiB | 6.29 MiB | 12.90 MiB | | 325 | reinvent@10.0.4.4 | 1254 | 6.38 MiB | 5.21 KiB | 6.29 MiB | 12.99 MiB | | 705 | reinvent@10.0.4.4 | 1273 | 6.37 MiB | 5.13 KiB | 6.29 MiB | 13.03 MiB | | 530 | reinvent@10.0.4.4 | 1268 | 6.37 MiB | 5.15 KiB | 6.29 MiB | 12.92 MiB | | 307 | reinvent@10.0.4.4 | 1263 | 6.37 MiB | 5.17 KiB | 6.29 MiB | 12.87 MiB | | 738 | reinvent@10.0.4.4 | 1260 | 6.37 MiB | 5.18 KiB | 6.29 MiB | 13.00 MiB | | 819 | reinvent@10.0.4.4 | 1252 | 6.37 MiB | 5.21 KiB | 6.29 MiB | 13.01 MiB | | 31 | innodb/srv_purge_thread | 17810 | 3.14 MiB | 184 bytes | 2.40 MiB | 205.69 MiB | | 38 | rdsadmin@localhost | 599 | 1.76 MiB | 3.01 KiB | 1.00 MiB | 25.58 MiB | | 1 | sql/main | 3756 | 1.32 MiB | 367 bytes | 355.78 KiB | 6.19 MiB | | 854 | rdsadmin@localhost | 46 | 1.08 MiB | 23.98 KiB | 1.00 MiB | 5.10 MiB | | 30 | innodb/clone_gtid_thread | 1596 | 573.14 KiB | 367 bytes | 254.91 KiB | 970.69 KiB | | 40 | rdsadmin@localhost | 235 | 245.19 KiB | 1.04 KiB | 128.88 KiB | 808.64 KiB | | 853 | rdsadmin@localhost | 96 | 94.63 KiB | 1009 bytes | 29.73 KiB | 422.45 KiB | | 36 | rdsadmin@localhost | 33 | 36.29 KiB | 1.10 KiB | 16.08 KiB | 74.15 MiB | | 33 | sql/event_scheduler | 3 | 16.27 KiB | 5.42 KiB | 16.04 KiB | 16.27 KiB | | 35 | sql/compress_gtid_table | 8 | 14.20 KiB | 1.77 KiB | 8.05 KiB | 18.62 KiB | | 25 | innodb/fts_optimize_thread | 12 | 1.86 KiB | 158 bytes | 648 bytes | 1.98 KiB | | 23 | innodb/srv_master_thread | 11 | 1.23 KiB | 114 bytes | 361 bytes | 24.40 KiB | | 24 | innodb/dict_stats_thread | 11 | 1.23 KiB | 114 bytes | 361 bytes | 1.35 KiB | | 5 | innodb/io_read_thread | 1 | 144 bytes | 144 bytes | 144 bytes | 144 bytes | | 6 | innodb/io_read_thread | 1 | 144 bytes | 144 bytes | 144 bytes | 144 bytes | | 2 | sql/aws_oscar_log_level_monitor | 0 | 0 bytes | 0 bytes | 0 bytes | 0 bytes | | 4 | innodb/io_ibuf_thread | 0 | 0 bytes | 0 bytes | 0 bytes | 0 bytes | | 7 | innodb/io_write_thread | 0 | 0 bytes | 0 bytes | 0 bytes | 0 bytes | | 8 | innodb/io_write_thread | 0 | 0 bytes | 0 bytes | 0 bytes | 0 bytes | | 9 | innodb/io_write_thread | 0 | 0 bytes | 0 bytes | 0 bytes | 0 bytes | | 10 | innodb/io_write_thread | 0 | 0 bytes | 0 bytes | 0 bytes | 0 bytes | | 11 | innodb/srv_lra_thread | 0 | 0 bytes | 0 bytes | 0 bytes | 0 bytes | | 12 | innodb/srv_akp_thread | 0 | 0 bytes | 0 bytes | 0 bytes | 0 bytes | | 18 | innodb/srv_lock_timeout_thread | 0 | 0 bytes | 0 bytes | 0 bytes | 248 bytes | | 19 | innodb/srv_error_monitor_thread | 0 | 0 bytes | 0 bytes | 0 bytes | 0 bytes | | 20 | innodb/srv_monitor_thread | 0 | 0 bytes | 0 bytes | 0 bytes | 0 bytes | | 21 | innodb/buf_resize_thread | 0 | 0 bytes | 0 bytes | 0 bytes | 0 bytes | | 22 | innodb/btr_search_sys_toggle_thread | 0 | 0 bytes | 0 bytes | 0 bytes | 0 bytes | | 32 | innodb/dict_persist_metadata_table_thread | 0 | 0 bytes | 0 bytes | 0 bytes | 0 bytes | | 34 | sql/signal_handler | 0 | 0 bytes | 0 bytes | 0 bytes | 0 bytes | +-----------+-------------------------------------------+--------------------+-------------------+-------------------+-------------------+-----------------+ 831 rows in set (2.48 sec)

앞서 설명한 것처럼 여기서 스레드 ID(thd_id) 값은 서버 백그라운드 스레드 또는 데이터베이스 연결을 참조할 수 있습니다. 스레드 ID 값을 데이터베이스 연결 ID에 매핑하려면 performance_schema.threads 테이블 또는 sys.processlist 뷰를 사용할 수 있으며, 연결 ID는 conn_id입니다.

mysql> SELECT thd_id,conn_id,user,db,command,state,time,last_wait FROM sys.processlist WHERE user='reinvent@10.0.4.4'; +--------+---------+-------------------+----------+---------+----------------+------+-------------------------------------------------+ | thd_id | conn_id | user | db | command | state | time | last_wait | +--------+---------+-------------------+----------+---------+----------------+------+-------------------------------------------------+ | 590 | 562 | reinvent@10.0.4.4 | sysbench | Execute | closing tables | 0 | wait/io/redo_log_flush | | 578 | 550 | reinvent@10.0.4.4 | sysbench | Sleep | NULL | 0 | idle | | 579 | 551 | reinvent@10.0.4.4 | sysbench | Execute | closing tables | 0 | wait/io/redo_log_flush | | 580 | 552 | reinvent@10.0.4.4 | sysbench | Execute | updating | 0 | wait/io/table/sql/handler | | 581 | 553 | reinvent@10.0.4.4 | sysbench | Execute | updating | 0 | wait/io/table/sql/handler | | 582 | 554 | reinvent@10.0.4.4 | sysbench | Sleep | NULL | 0 | idle | | 583 | 555 | reinvent@10.0.4.4 | sysbench | Sleep | NULL | 0 | idle | | 584 | 556 | reinvent@10.0.4.4 | sysbench | Execute | updating | 0 | wait/io/table/sql/handler | | 585 | 557 | reinvent@10.0.4.4 | sysbench | Execute | closing tables | 0 | wait/io/redo_log_flush | | 586 | 558 | reinvent@10.0.4.4 | sysbench | Execute | updating | 0 | wait/io/table/sql/handler | | 587 | 559 | reinvent@10.0.4.4 | sysbench | Execute | closing tables | 0 | wait/io/redo_log_flush | . . . . . . | 323 | 295 | reinvent@10.0.4.4 | sysbench | Sleep | NULL | 0 | idle | | 324 | 296 | reinvent@10.0.4.4 | sysbench | Execute | updating | 0 | wait/io/table/sql/handler | | 325 | 297 | reinvent@10.0.4.4 | sysbench | Execute | closing tables | 0 | wait/io/redo_log_flush | | 326 | 298 | reinvent@10.0.4.4 | sysbench | Execute | updating | 0 | wait/io/table/sql/handler | | 438 | 410 | reinvent@10.0.4.4 | sysbench | Execute | System lock | 0 | wait/lock/table/sql/handler | | 280 | 252 | reinvent@10.0.4.4 | sysbench | Sleep | starting | 0 | wait/io/socket/sql/client_connection | | 98 | 70 | reinvent@10.0.4.4 | sysbench | Query | freeing items | 0 | NULL | +--------+---------+-------------------+----------+---------+----------------+------+-------------------------------------------------+ 804 rows in set (5.51 sec)

이제 sysbench 워크로드를 중지하여 연결을 닫고 메모리를 해제합니다. 이벤트를 다시 확인해 보면 메모리가 해제된 것을 확인할 수 있지만, high_alloc을 통해 최고 수치를 계속 확인할 수 있습니다. high_alloc 열은 현재 할당된 메모리만 보여주는 current_alloc의 메모리 사용량을 즉시 식별하지 못할 수도 있는 단기 메모리 사용량 급증을 식별하는 데 매우 유용할 수 있습니다.

mysql> SELECT * FROM sys.memory_global_by_current_bytes WHERE event_name='memory/sql/Prepared_statement::main_mem_root' LIMIT 10; +----------------------------------------------+---------------+---------------+-------------------+------------+------------+----------------+ | event_name | current_count | current_alloc | current_avg_alloc | high_count | high_alloc | high_avg_alloc | +----------------------------------------------+---------------+---------------+-------------------+------------+------------+----------------+ | memory/sql/Prepared_statement::main_mem_root | 17 | 253.80 KiB | 14.93 KiB | 512823 | 4.91 GiB | 10.04 KiB | +----------------------------------------------+---------------+---------------+-------------------+------------+------------+----------------+ 1 row in set (0.00 sec)

high_alloc을 재설정하려는 경우 performance_schema 메모리 요약 테이블을 잘라낼 수 있지만 이렇게 하면 모든 메모리 계측이 재설정됩니다. 자세한 내용은 MySQL 설명서의 성능 스키마 일반 테이블 특성을 참조하세요.

다음 예제에서는 잘린 후 high_alloc이 재설정되는 것을 볼 수 있습니다.

mysql> TRUNCATE `performance_schema`.`memory_summary_global_by_event_name`; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM sys.memory_global_by_current_bytes WHERE event_name='memory/sql/Prepared_statement::main_mem_root' LIMIT 10; +----------------------------------------------+---------------+---------------+-------------------+------------+------------+----------------+ | event_name | current_count | current_alloc | current_avg_alloc | high_count | high_alloc | high_avg_alloc | +----------------------------------------------+---------------+---------------+-------------------+------------+------------+----------------+ | memory/sql/Prepared_statement::main_mem_root | 17 | 253.80 KiB | 14.93 KiB | 17 | 253.80 KiB | 14.93 KiB | +----------------------------------------------+---------------+---------------+-------------------+------------+------------+----------------+ 1 row in set (0.00 sec)

예제 2: 일시적인 메모리 급증

또 다른 일반적인 현상은 데이터베이스 서버의 메모리 사용량이 일시적으로 급증하는 것입니다. 사용 가능한 메모리가 주기적으로 떨어지면 메모리가 이미 비워졌기 때문에 sys.memory_global_by_current_bytes에서 current_alloc을 사용할 때 문제를 해결하기가 어려울 수 있습니다.

참고

성능 스키마 통계를 재설정하거나 데이터베이스 인스턴스를 다시 시작한 경우 sys 또는 performance_schema에서 이 정보를 사용할 수 없습니다. 이 정보를 유지하려면 외부 지표 수집을 구성하는 것이 좋습니다.

향상된 모니터링의 다음 os.memory.free 지표 그래프는 7초간의 단기 메모리 사용량 급증을 보여줍니다. 향상된 모니터링을 통해 1초 정도의 짧은 간격으로 모니터링할 수 있어 이와 같은 일시적 급증을 포착하는 데 적합합니다.

시간 경과에 따른 일시적 메모리 사용량 급증과 잠재적 메모리 관리 문제를 나타내는 주기적 패턴을 보여주는 그래프입니다.

여기서 메모리 사용량의 원인을 진단하는 데 도움이 되도록 sys 메모리 요약 뷰의 high_alloc성능 스키마 문 요약 테이블을 함께 사용하여 문제가 되는 세션 및 연결을 식별할 수 있습니다.

예상한 바와 같이 현재 메모리 사용량이 많지 않으므로 current_allocsys 스키마 뷰에서 주요 문제 인자를 확인할 수 없습니다.

mysql> SELECT * FROM sys.memory_global_by_current_bytes LIMIT 10; +-----------------------------------------------------------------------------+---------------+---------------+-------------------+------------+------------+----------------+ | event_name | current_count | current_alloc | current_avg_alloc | high_count | high_alloc | high_avg_alloc | +-----------------------------------------------------------------------------+---------------+---------------+-------------------+------------+------------+----------------+ | memory/innodb/hash0hash | 4 | 79.07 MiB | 19.77 MiB | 4 | 79.07 MiB | 19.77 MiB | | memory/innodb/os0event | 439372 | 60.34 MiB | 144 bytes | 439372 | 60.34 MiB | 144 bytes | | memory/performance_schema/events_statements_summary_by_digest | 1 | 40.28 MiB | 40.28 MiB | 1 | 40.28 MiB | 40.28 MiB | | memory/mysys/KEY_CACHE | 3 | 16.00 MiB | 5.33 MiB | 3 | 16.00 MiB | 5.33 MiB | | memory/performance_schema/events_statements_history_long | 1 | 14.34 MiB | 14.34 MiB | 1 | 14.34 MiB | 14.34 MiB | | memory/performance_schema/events_errors_summary_by_thread_by_error | 257 | 13.07 MiB | 52.06 KiB | 257 | 13.07 MiB | 52.06 KiB | | memory/performance_schema/events_statements_summary_by_thread_by_event_name | 1 | 11.81 MiB | 11.81 MiB | 1 | 11.81 MiB | 11.81 MiB | | memory/performance_schema/events_statements_summary_by_digest.digest_text | 1 | 9.77 MiB | 9.77 MiB | 1 | 9.77 MiB | 9.77 MiB | | memory/performance_schema/events_statements_history_long.digest_text | 1 | 9.77 MiB | 9.77 MiB | 1 | 9.77 MiB | 9.77 MiB | | memory/performance_schema/events_statements_history_long.sql_text | 1 | 9.77 MiB | 9.77 MiB | 1 | 9.77 MiB | 9.77 MiB | +-----------------------------------------------------------------------------+---------------+---------------+-------------------+------------+------------+----------------+ 10 rows in set (0.01 sec)

뷰를 high_alloc 기준으로 정렬하여 펼치면 이제 memory/temptable/physical_ram 구성 요소가 매우 적합한 후보임을 알 수 있습니다. 최대 용량으로는 515.00MiB를 소비했습니다.

이름에서 알 수 있듯이 memory/temptable/physical_ram은 MySQL 8.0에 도입된 MySQL의 TEMP 스토리지 엔진의 메모리 사용량을 측정합니다. MySQL에서 임시 테이블을 사용하는 방법에 대한 자세한 내용은 MySQL 설명서의 MySQL의 내부 임시 테이블 사용을 참조하세요.

참고

이 예제에서는 sys.x$memory_global_by_current_bytes 뷰를 사용합니다.

mysql> SELECT event_name, format_bytes(current_alloc) AS "currently allocated", sys.format_bytes(high_alloc) AS "high-water mark" FROM sys.x$memory_global_by_current_bytes ORDER BY high_alloc DESC LIMIT 10; +-----------------------------------------------------------------------------+---------------------+-----------------+ | event_name | currently allocated | high-water mark | +-----------------------------------------------------------------------------+---------------------+-----------------+ | memory/temptable/physical_ram | 4.00 MiB | 515.00 MiB | | memory/innodb/hash0hash | 79.07 MiB | 79.07 MiB | | memory/innodb/os0event | 63.95 MiB | 63.95 MiB | | memory/performance_schema/events_statements_summary_by_digest | 40.28 MiB | 40.28 MiB | | memory/mysys/KEY_CACHE | 16.00 MiB | 16.00 MiB | | memory/performance_schema/events_statements_history_long | 14.34 MiB | 14.34 MiB | | memory/performance_schema/events_errors_summary_by_thread_by_error | 13.07 MiB | 13.07 MiB | | memory/performance_schema/events_statements_summary_by_thread_by_event_name | 11.81 MiB | 11.81 MiB | | memory/performance_schema/events_statements_summary_by_digest.digest_text | 9.77 MiB | 9.77 MiB | | memory/performance_schema/events_statements_history_long.sql_text | 9.77 MiB | 9.77 MiB | +-----------------------------------------------------------------------------+---------------------+-----------------+ 10 rows in set (0.00 sec)

예제 1: 지속적인 높은 메모리 사용량에서는 각 연결의 현재 메모리 사용량을 확인하여 문제의 메모리 사용을 담당하는 연결을 확인했습니다. 이 예제에서는 메모리가 이미 비워졌으므로 현재 연결의 메모리 사용량을 확인하는 것은 유용하지 않습니다.

더 자세히 알아보고 문제가 되는 문, 사용자, 호스트를 찾기 위해 성능 스키마를 사용합니다. 성능 스키마에는 이벤트 이름, 문 다이제스트, 호스트, 스레드, 사용자 등 다양한 차원으로 구분된 여러 문 요약 테이블이 포함되어 있습니다. 각 뷰를 통해 특정 문이 실행되는 위치와 수행하는 작업을 더 자세히 살펴볼 수 있습니다. 이 섹션은 MAX_TOTAL_MEMORY를 중점적으로 다루지만, 사용 가능한 모든 열에 대한 자세한 내용은 성능 스키마 문 요약 테이블 설명서에서 확인할 수 있습니다.

mysql> SHOW TABLES IN performance_schema LIKE 'events_statements_summary_%'; +------------------------------------------------------------+ | Tables_in_performance_schema (events_statements_summary_%) | +------------------------------------------------------------+ | events_statements_summary_by_account_by_event_name | | events_statements_summary_by_digest | | events_statements_summary_by_host_by_event_name | | events_statements_summary_by_program | | events_statements_summary_by_thread_by_event_name | | events_statements_summary_by_user_by_event_name | | events_statements_summary_global_by_event_name | +------------------------------------------------------------+ 7 rows in set (0.00 sec)

먼저 events_statements_summary_by_digest를 확인해 MAX_TOTAL_MEMORY를 살펴봅니다.

여기서 다음 내용을 확인할 수 있습니다.

  • 다이제스트 20676ce4a690592ff05debcffcbc26faeb76f22005e7628364d7a498769d0c4a가 포함된 쿼리가 이 메모리 사용량에 적합한 것으로 보입니다. MAX_TOTAL_MEMORY는 5537450710으로, sys.x$memory_global_by_current_bytesmemory/temptable/physical_ram 이벤트에서 살펴본 최고 수치와 일치합니다.

  • 이는 4번(COUNT_STAR) 실행되었는데, 처음은 2024-03-26 04:08:34.943256에, 마지막은 2024-03-26 04:43:06.998310에 실행되었습니다.

mysql> SELECT SCHEMA_NAME,DIGEST,COUNT_STAR,MAX_TOTAL_MEMORY,FIRST_SEEN,LAST_SEEN FROM performance_schema.events_statements_summary_by_digest ORDER BY MAX_TOTAL_MEMORY DESC LIMIT 5; +-------------+------------------------------------------------------------------+------------+------------------+----------------------------+----------------------------+ | SCHEMA_NAME | DIGEST | COUNT_STAR | MAX_TOTAL_MEMORY | FIRST_SEEN | LAST_SEEN | +-------------+------------------------------------------------------------------+------------+------------------+----------------------------+----------------------------+ | sysbench | 20676ce4a690592ff05debcffcbc26faeb76f22005e7628364d7a498769d0c4a | 4 | 537450710 | 2024-03-26 04:08:34.943256 | 2024-03-26 04:43:06.998310 | | NULL | f158282ea0313fefd0a4778f6e9b92fc7d1e839af59ebd8c5eea35e12732c45d | 4 | 3636413 | 2024-03-26 04:29:32.712348 | 2024-03-26 04:36:26.269329 | | NULL | 0046bc5f642c586b8a9afd6ce1ab70612dc5b1fd2408fa8677f370c1b0ca3213 | 2 | 3459965 | 2024-03-26 04:31:37.674008 | 2024-03-26 04:32:09.410718 | | NULL | 8924f01bba3c55324701716c7b50071a60b9ceaf17108c71fd064c20c4ab14db | 1 | 3290981 | 2024-03-26 04:31:49.751506 | 2024-03-26 04:31:49.751506 | | NULL | 90142bbcb50a744fcec03a1aa336b2169761597ea06d85c7f6ab03b5a4e1d841 | 1 | 3131729 | 2024-03-26 04:15:09.719557 | 2024-03-26 04:15:09.719557 | +-------------+------------------------------------------------------------------+------------+------------------+----------------------------+----------------------------+ 5 rows in set (0.00 sec)

이제 문제가 되는 다이제스트를 알았으므로 쿼리 텍스트, 실행한 사용자, 실행 위치 등의 세부 정보를 더 자세히 확인할 수 있습니다. 반환된 다이제스트 텍스트를 바탕으로 이는 임시 테이블 4개를 만들고 테이블 스캔을 4회 수행하는 일반적인 테이블 표현식(CTE)이며, 매우 비효율적이라는 것을 알 수 있습니다.

mysql> SELECT SCHEMA_NAME,DIGEST_TEXT,QUERY_SAMPLE_TEXT,MAX_TOTAL_MEMORY,SUM_ROWS_SENT,SUM_ROWS_EXAMINED,SUM_CREATED_TMP_TABLES,SUM_NO_INDEX_USED FROM performance_schema.events_statements_summary_by_digest WHERE DIGEST='20676ce4a690592ff05debcffcbc26faeb76f22005e7628364d7a498769d0c4a'\G; *************************** 1. row *************************** SCHEMA_NAME: sysbench DIGEST_TEXT: WITH RECURSIVE `cte` ( `n` ) AS ( SELECT ? FROM `sbtest1` UNION ALL SELECT `id` + ? FROM `sbtest1` ) SELECT * FROM `cte` QUERY_SAMPLE_TEXT: WITH RECURSIVE cte (n) AS ( SELECT 1 from sbtest1 UNION ALL SELECT id + 1 FROM sbtest1) SELECT * FROM cte MAX_TOTAL_MEMORY: 537450710 SUM_ROWS_SENT: 80000000 SUM_ROWS_EXAMINED: 80000000 SUM_CREATED_TMP_TABLES: 4 SUM_NO_INDEX_USED: 4 1 row in set (0.01 sec)

events_statements_summary_by_digest 테이블 및 기타 성능 스키마 문 요약 테이블에 대한 자세한 내용은 MySQL 설명서의 문 요약 테이블을 참조하세요.

EXPLAIN 또는 EXPLAIN ANALYZE 문을 실행하여 자세한 내용을 확인할 수도 있습니다.

참고

EXPLAIN ANALYZEEXPLAIN보다 많은 정보를 제공할 수 있지만 쿼리를 실행하기도 하므로 주의해야 합니다.

-- EXPLAIN mysql> EXPLAIN WITH RECURSIVE cte (n) AS (SELECT 1 FROM sbtest1 UNION ALL SELECT id + 1 FROM sbtest1) SELECT * FROM cte; +----+-------------+------------+------------+-------+---------------+------+---------+------+----------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+------------+------------+-------+---------------+------+---------+------+----------+----------+-------------+ | 1 | PRIMARY | <derived2> | NULL | ALL | NULL | NULL | NULL | NULL | 19221520 | 100.00 | NULL | | 2 | DERIVED | sbtest1 | NULL | index | NULL | k_1 | 4 | NULL | 9610760 | 100.00 | Using index | | 3 | UNION | sbtest1 | NULL | index | NULL | k_1 | 4 | NULL | 9610760 | 100.00 | Using index | +----+-------------+------------+------------+-------+---------------+------+---------+------+----------+----------+-------------+ 3 rows in set, 1 warning (0.00 sec) -- EXPLAIN format=tree mysql> EXPLAIN format=tree WITH RECURSIVE cte (n) AS (SELECT 1 FROM sbtest1 UNION ALL SELECT id + 1 FROM sbtest1) SELECT * FROM cte\G; *************************** 1. row *************************** EXPLAIN: -> Table scan on cte (cost=4.11e+6..4.35e+6 rows=19.2e+6) -> Materialize union CTE cte (cost=4.11e+6..4.11e+6 rows=19.2e+6) -> Index scan on sbtest1 using k_1 (cost=1.09e+6 rows=9.61e+6) -> Index scan on sbtest1 using k_1 (cost=1.09e+6 rows=9.61e+6) 1 row in set (0.00 sec) -- EXPLAIN ANALYZE mysql> EXPLAIN ANALYZE WITH RECURSIVE cte (n) AS (SELECT 1 from sbtest1 UNION ALL SELECT id + 1 FROM sbtest1) SELECT * FROM cte\G; *************************** 1. row *************************** EXPLAIN: -> Table scan on cte (cost=4.11e+6..4.35e+6 rows=19.2e+6) (actual time=6666..9201 rows=20e+6 loops=1) -> Materialize union CTE cte (cost=4.11e+6..4.11e+6 rows=19.2e+6) (actual time=6666..6666 rows=20e+6 loops=1) -> Covering index scan on sbtest1 using k_1 (cost=1.09e+6 rows=9.61e+6) (actual time=0.0365..2006 rows=10e+6 loops=1) -> Covering index scan on sbtest1 using k_1 (cost=1.09e+6 rows=9.61e+6) (actual time=0.0311..2494 rows=10e+6 loops=1) 1 row in set (10.53 sec)

하지만 누가 실행했을까요? 성능 스키마에서 destructive_operator 사용자가 537450710의 MAX_TOTAL_MEMORY를 보유한 것을 확인할 수 있는데, 이 역시 이전 결과와 일치합니다.

참고

성능 스키마는 메모리에 저장되므로 감사의 유일한 소스로 사용해서는 안 됩니다. 문의 실행 내역과 사용자 기록을 관리해야 하는 경우 Aurora 고급 감사를 사용 설정하는 것이 좋습니다. 메모리 사용량에 대한 정보도 유지해야 하는 경우 이러한 값을 내보내고 저장하도록 모니터링을 구성하는 것이 좋습니다.

mysql> SELECT USER,EVENT_NAME,COUNT_STAR,MAX_TOTAL_MEMORY FROM performance_schema.events_statements_summary_by_user_by_event_name ORDER BY MAX_CONTROLLED_MEMORY DESC LIMIT 5; +----------------------+---------------------------+------------+------------------+ | USER | EVENT_NAME | COUNT_STAR | MAX_TOTAL_MEMORY | +----------------------+---------------------------+------------+------------------+ | destructive_operator | statement/sql/select | 4 | 537450710 | | rdsadmin | statement/sql/select | 4172 | 3290981 | | rdsadmin | statement/sql/show_tables | 2 | 3615821 | | rdsadmin | statement/sql/show_fields | 2 | 3459965 | | rdsadmin | statement/sql/show_status | 75 | 1914976 | +----------------------+---------------------------+------------+------------------+ 5 rows in set (0.00 sec) mysql> SELECT HOST,EVENT_NAME,COUNT_STAR,MAX_TOTAL_MEMORY FROM performance_schema.events_statements_summary_by_host_by_event_name WHERE HOST != 'localhost' AND COUNT_STAR>0 ORDER BY MAX_CONTROLLED_MEMORY DESC LIMIT 5; +------------+----------------------+------------+------------------+ | HOST | EVENT_NAME | COUNT_STAR | MAX_TOTAL_MEMORY | +------------+----------------------+------------+------------------+ | 10.0.8.231 | statement/sql/select | 4 | 537450710 | +------------+----------------------+------------+------------------+ 1 row in set (0.00 sec)

예시 3: 여유 메모리가 지속적으로 삭제되고 회수되지 않음

InnoDB 데이터베이스 엔진은 다양한 구성 요소에 대해 다양한 특수 메모리 추적 이벤트를 사용합니다. 이러한 특정 이벤트를 통해 주요 InnoDB 하위 시스템의 메모리 사용량을 세부적으로 추적할 수 있습니다. 예를 들면 다음과 같습니다.

  • memory/innodb/buf0buf - InnoDB 버퍼 풀에 대한 메모리 할당 모니터링을 전담합니다.

  • memory/innodb/ibuf0ibuf - 특히 InnoDB 변경 버퍼와 관련된 메모리 변경 사항을 추적합니다.

메모리의 상위 소비자를 식별하기 위해 sys.memory_global_by_current_bytes를 쿼리할 수 있습니다.

mysql> SELECT event_name,current_alloc FROM sys.memory_global_by_current_bytes LIMIT 10; +-----------------------------------------------------------------+---------------+ | event_name | current_alloc | +-----------------------------------------------------------------+---------------+ | memory/innodb/memory | 5.28 GiB | | memory/performance_schema/table_io_waits_summary_by_index_usage | 495.00 MiB | | memory/performance_schema/table_shares | 488.00 MiB | | memory/sql/TABLE_SHARE::mem_root | 388.95 MiB | | memory/innodb/std | 226.88 MiB | | memory/innodb/fil0fil | 198.49 MiB | | memory/sql/binlog_io_cache | 128.00 MiB | | memory/innodb/mem0mem | 96.82 MiB | | memory/innodb/dict0dict | 96.76 MiB | | memory/performance_schema/rwlock_instances | 88.00 MiB | +-----------------------------------------------------------------+---------------+ 10 rows in set (0.00 sec)

결과는 memory/innodb/memory가 현재 할당된 메모리의 5.28GiB를 사용하는 상위 소비자임을 보여줍니다. 이 이벤트는 앞에서 언급한 memory/innodb/buf0buf와 같이 보다 구체적인 대기 이벤트와 관련이 없는 다양한 InnoDB 구성 요소에서 메모리 할당을 위한 범주 역할을 합니다.

InnoDB 구성 요소가 메모리의 기본 소비자임을 확인한 후 다음 MySQL 명령을 사용하여 세부 정보를 자세히 살펴볼 수 있습니다.

SHOW ENGINE INNODB STATUS \G;

SHOW ENGINE INNODB STATUS 명령은 다양한 InnoDB 구성 요소에 대한 자세한 메모리 사용량 통계를 포함하여 InnoDB 스토리지 엔진에 대한 포괄적인 상태 보고서를 제공합니다. 이를 통해 가장 많은 메모리를 소비하는 특정 InnoDB 구조 또는 작업을 식별할 수 있습니다. 자세한 내용은 MySQL 설명서에서 InnoDB in-memory structures를 참조하세요.

InnoDB 상태 보고서의 BUFFER POOL AND MEMORY 섹션을 분석하면 memory/innodb/memory가 추적하는 메모리의 89%를 차지하는 5,051,647,748바이트(4.7GiB)가 딕셔너리 객체 캐시에 할당되어 있는 것을 확인할 수 있습니다.

---------------------- BUFFER POOL AND MEMORY ---------------------- Total large memory allocated 0 Dictionary memory allocated 5051647748 Buffer pool size 170512 Free buffers 142568 Database pages 27944 Old database pages 10354 Modified db pages 6 Pending reads 0

딕셔너리 객체 캐시는 이전에 액세스한 데이터 딕셔너리 객체를 메모리에 저장하여 객체 재사용을 가능하게 하고 성능을 개선하는 공유 글로벌 캐시입니다. 딕셔너리 객체 캐시에 메모리가 많이 할당되어 있다는 것은 데이터 딕셔너리 캐시에 데이터베이스 객체가 많다는 것을 의미합니다.

데이터 딕셔너리 캐시가 주된 소비자임을 알았으므로 이제 데이터 딕셔너리 캐시에서 열린 테이블을 검사합니다. 테이블 정의 캐시에서 테이블 수를 찾으려면 글로벌 상태 변수 open_table_definitions을 쿼리합니다.

mysql> show global status like 'open_table_definitions'; +------------------------+-------+ | Variable_name | Value | +------------------------+-------+ | Open_table_definitions | 20000 | +------------------------+-------+ 1 row in set (0.00 sec)

자세한 내용은 MySQL 설명서의 MySQL에서 테이블을 열고 닫는 방법을 참조하십시오.

DB 클러스터 또는 DB 인스턴스 파라미터 그룹에서 table_definition_cache 파라미터를 제한하여 데이터 딕셔너리 캐시의 테이블 정의 수를 제한할 수 있습니다. Aurora MySQL의 경우 이 값은 테이블 정의 캐시의 테이블 수에 대한 소프트 제한 역할을 합니다. 기본값은 인스턴스 클래스에 따라 달라지며 다음과 같이 설정됩니다.

LEAST({DBInstanceClassMemory/393040}, 20000)

테이블 수가 table_definition_cache 한도를 초과하면 가장 오래전에 사용됨(LRU) 메커니즘이 캐시에서 테이블을 없애고 제거합니다. 그러나 외래 키 관계와 관련된 테이블은 LRU 목록에 배치되지 않으므로 제거가 불가능합니다.

현재 시나리오에서는 FLUSH TABLES을 실행하여 테이블 정의 캐시를 지웁니다. 이 작업을 수행하면 다음과 같이 Open_table_definitions 글로벌 상태 변수가 2만에서 12로 크게 감소합니다.

mysql> show global status like 'open_table_definitions'; +------------------------+-------+ | Variable_name | Value | +------------------------+-------+ | Open_table_definitions | 12 | +------------------------+-------+ 1 row in set (0.00 sec)

이러한 감소에도 불구하고 memory/innodb/memory에 대한 메모리 할당은 5.18GiB로 높게 유지되고 할당된 딕셔너리 메모리도 변경되지 않는 것으로 관찰됩니다. 이는 다음 쿼리 결과에서 확실히 알 수 있습니다.

mysql> SELECT event_name,current_alloc FROM sys.memory_global_by_current_bytes LIMIT 10; +-----------------------------------------------------------------+---------------+ | event_name | current_alloc | +-----------------------------------------------------------------+---------------+ | memory/innodb/memory | 5.18 GiB | | memory/performance_schema/table_io_waits_summary_by_index_usage | 495.00 MiB | | memory/performance_schema/table_shares | 488.00 MiB | | memory/sql/TABLE_SHARE::mem_root | 388.95 MiB | | memory/innodb/std | 226.88 MiB | | memory/innodb/fil0fil | 198.49 MiB | | memory/sql/binlog_io_cache | 128.00 MiB | | memory/innodb/mem0mem | 96.82 MiB | | memory/innodb/dict0dict | 96.76 MiB | | memory/performance_schema/rwlock_instances | 88.00 MiB | +-----------------------------------------------------------------+---------------+ 10 rows in set (0.00 sec)
---------------------- BUFFER POOL AND MEMORY ---------------------- Total large memory allocated 0 Dictionary memory allocated 5001599639 Buffer pool size 170512 Free buffers 142568 Database pages 27944 Old database pages 10354 Modified db pages 6 Pending reads 0

이렇게 지속적으로 높은 메모리 사용량은 외래 키 관계와 관련된 테이블 때문일 수 있습니다. 이러한 테이블은 제거를 위해 LRU 목록에 배치되지 않으므로 테이블 정의 캐시를 플러싱한 후에도 메모리 할당이 높은 상태를 유지하는 이유가 설명됩니다.

이 문제를 해결하려면:

  1. 데이터베이스 스키마, 특히 외래 키 관계를 검토하고 최적화하세요.

  2. 딕셔너리 객체를 수용할 수 있는 메모리가 더 많은 더 큰 DB 인스턴스 클래스로 이동하는 것을 고려해 보세요.

다음 단계에 따라 메모리 할당 패턴을 이해하면 Aurora MySQL DB 인스턴스의 메모리 사용량을 더 잘 관리하고 메모리 압박으로 인한 잠재적 성능 문제를 방지할 수 있습니다.