Aurora MySQL データベースのメモリ使用量に関する問題のトラブルシューティング - Amazon Aurora

Aurora MySQL データベースのメモリ使用量に関する問題のトラブルシューティング

CloudWatch、拡張モニタリング、Performance Insights は、オペレーティングシステムレベルでのメモリ使用量 (データベースプロセスによるメモリ使用量など) の概要を提供しますが、エンジン内の接続やコンポーネント別のメモリ使用量を詳しく知ることはできません。

このトラブルシューティングには、パフォーマンススキーマと sys スキーマを使用できます。Aurora MySQL バージョン 3 では、パフォーマンススキーマを有効にすると、追加の計測がデフォルトで有効になります。Aurora MySQL バージョン 2 では、パフォーマンススキーマのメモリ使用量の計測のみがデフォルトで有効になります。パフォーマンススキーマでメモリ使用量を追跡するために使用できるテーブルと、パフォーマンススキーマのメモリ計測の有効化の詳細については、MySQL ドキュメントの「Memory summary tables」を参照してください。パフォーマンススキーマと Performance Insights の詳細については、「Aurora MySQL における Performance Insights のPerformance Schema の概要」を参照してください。

パフォーマンススキーマでは、現在のメモリ使用量を追跡するための詳細情報を参照できます。一方、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 ドキュメントの「Performance Schema instrument naming conventions」を参照してください。

次のクエリから、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 ドキュメントの「The Performance Schema memory-allocation model」を参照してください。

見やすくするために、パフォーマンススキーマイベントを除外して同じクエリを再実行できます。出力は、次のように表示されます。

  • メモリ使用量が多いのは memory/sql/Prepared_statement::main_mem_root です。

  • current_alloc 列を見ると、MySQL では、このイベントに現在 4.91 GiB が割り当てられていることがわかります。

  • high_alloc column によると、4.91 GiB は、統計の最後のリセット後またはサーバーの再起動後からの 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 を参照できます。

次の例では、各接続に約 7 MiB が割り当てられ、ハイウォーターマークは約 6.29 MiB (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 ビューを使用できます。conn_id は接続 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)

performance_schema をリセットする場合は、high_alloc のメモリ概要テーブルを切り捨てることができますが、これに伴ってすべてのメモリ計測がリセットされます。詳細については、MySQL ドキュメントの「Performance Schema general table characteristics」を参照してください。

次の例では、切り捨て後に 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: 一時的なメモリスパイク

もう 1 つのよくある現象は、データベースサーバーでメモリ使用量が短時間に急増することです。これは空きメモリの定期的な低下を示している場合があります。メモリは解放済みであるため、sys.memory_global_by_current_bytescurrent_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.00 MiB になっています。

その名前が示すように、memory/temptable/physical_ram は、MySQL 8.0 で MySQL に導入された TEMP ストレージエンジンのメモリ使用量を計測します。MySQL で一時テーブルを使用する方法の詳細については、MySQL ドキュメントの「Internal temporary table use in 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 は 537450710 で、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 ドキュメントの「Statement summary tables」を参照してください。

EXPLAIN または EXPLAIN ANALYZE ステートメントを実行して詳細を確認することもできます。

注記

EXPLAIN ANALYZE は、EXPLAIN よりも多くの情報を提供できますが、クエリも実行するので注意する必要があります。

-- 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 ユーザーの MAX_TOTAL_MEMORY が 537450710 になっており、前の結果と一致しています。

注記

パフォーマンススキーマはメモリに保存されるため、監査の唯一のソースとして依存すべきではありません。実行したステートメントやユーザーの履歴を保持する必要がある場合は、[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.28 GiB を使用していることを示しています。このイベントは、前述の 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 セクションを分析すると、5,051,647,748 バイト (4.7 GiB) がディクショナリオブジェクトキャッシュに割り当てられ、memory/innodb/memory が追跡するメモリの 89% を占めていることがわかります。

---------------------- 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 (least recently used) メカニズムはキャッシュからテーブルをエビクションして削除します。ただし、外部キー関係に関連するテーブルは LRU リストに配置されないため、削除されません。

現在のシナリオでは、FLUSH TABLES を実行してテーブル定義キャッシュをクリアします。このアクションにより、次に示すように、Open_table_definitions グローバルステータス変数が 20,000 から 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.18 GiB と高いままであり、割り当てられたディクショナリメモリにも変化がないことがわかります。これは、次のクエリ結果から明らかです。

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 インスタンスのメモリ使用量をより適切に管理し、メモリ負荷による潜在的なパフォーマンスの問題を防ぐことができます。