RDSのDBパラメータを変更して一時的なテーブル枯渇を解消する
はじめに
こんにちは、カスタマーサクセス部の奥井大和/やまとです。
ある日突然、Aurora MySQLのCPU使用率が99%に張り付き、ALBからは5XXエラーが頻発。これは多くのアプリケーションで直面するボトルネックです。
このような状況では、ALBやアプリケーションサーバー(EC2インスタンス)の問題に見えがちです。しかし、根本原因はデータベース層に潜んでいることも少なくありません。データベース(RDS)の性能が限界に達すると、その影響はアプリケーションサーバーの応答遅延やタイムアウトという形で波及し、最終的にユーザーと接するALBが5XXエラーを返すという連鎖反応を引き起こします。
本記事では、このような問題を エラーログの分析 から突き止めて、AWS CloudShellを使って安全に解決していきます。
原因の特定
まず、CPU使用率の上昇の原因をAuroraのエラーログから調査します。
Aurora and RDS > データベース > 対象RDSインスタンスの詳細から「ログとイベント」セクションを選び、「CPU使用率が急騰したタイミング」と同じ最終書き込み時刻のログを選択します。
ログには、CPU使用率が急騰したタイミングと一致して、以下のようなエラーメッセージが大量に記録されていることがあります。
YYYY-MM-DDThh:mm:ss.ssssssZ SESSION_ID [ERROR] [MY-013132] [Server] The table '/rdsdbdata/tmp/#sql*****' is full! (handler.cc:1234)
YYYY-MM-DDThh:mm:ss.ssssssZ SESSION_ID [ERROR] [MY-013132] [Server] The table '/rdsdbdata/tmp/#sql*****' is full! (handler.cc:1234)
YYYY-MM-DDThh:mm:ss.ssssssZ SESSION_ID [ERROR] [MY-013132] [Server] The table '/rdsdbdata/tmp/#sql*****' is full! (handler.cc:1234)
YYYY-MM-DDThh:mm:ss.ssssssZ SESSION_ID [ERROR] [MY-013132] [Server] The table '/rdsdbdata/tmp/#sql*****' is full! (handler.cc:1234)
YYYY-MM-DDThh:mm:ss.ssssssZ SESSION_ID [ERROR] [MY-013132] [Server] The table '/rdsdbdata/tmp/#sql*****' is full! (handler.cc:1234)
この「 The table ~ is full! 」というエラーが、今回の障害の原因になります。
これは、MySQLが複雑なクエリ(複数のテーブルを結合するJOIN
や、大量のデータを並べ替えるORDER BY
など)を実行するために内部的に使用する 「一時テーブル」の領域が不足した ことを意味します。
この一時テーブルは、クエリ専用の「作業スペース」であり、デフォルトの設定ではこの作業スペースが小さいため(多くの場合は16MB)、複雑なクエリが必要とする量を確保できず、処理がエラーとなっていました。
これにより、失敗したクエリはCPUリソースを掴んだまま滞留し、後続のクエリも次々と詰まっていくことで、CPU使用率が99%に達していたと考えられます。この発見により、対処すべきは、この「一時テーブル」のサイズを制御するDBパラメータであると推測できますね。
解決してみた
作業前の注意点
1: 事前確認-現在の構成の把握
1.1 現在のパラメータグループを確認する
対象のDBインスタンスに現在どのパラメータグループが適用されているか確認。
- 入力
# リードレプリカ1のパラメータグループ名を確認
aws rds describe-db-instances \
--db-instance-identifier my-aurora-instance-1 \
--query 'DBInstances[0].DBParameterGroups[0].DBParameterGroupName' \
--output text
# リードレプリカ2のパラメータグループ名を確認
aws rds describe-db-instances \
--db-instance-identifier my-aurora-instance-2 \
--query 'DBInstances[0].DBParameterGroups[0].DBParameterGroupName' \
--output text
- 出力
default.aurora-mysql8.0
1.2 現在のパラメータ値を確認する
次に、今回の問題に関わるtmp_table_size
(一時テーブルの最大サイズ)とmax_heap_table_size
(MEMORY テーブルの最大サイズ)の現在値を確認します。
- 入力
# <現在のパラメータグループ名>をSTEP1で確認した名前に置き換える
aws rds describe-db-parameters \
--db-parameter-group-name <現在のパラメータグループ名> \
--query 'Parameters[?ParameterName==`tmp_table_size`||ParameterName==`max_heap_table_size`]'
- 出力
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| DescribeDBParameters |
+---------------------------+-----------------+------------+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+----------------------+------------------+
| AllowedValues | ApplyMethod | ApplyType | DataType | Description | IsModifiable | ParameterName | Source |
+---------------------------+-----------------+------------+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+----------------------+------------------+
| 16384-1844674407370954752| pending-reboot | dynamic | integer | Maximum size to which MEMORY tables are allowed to grow. | True | max_heap_table_size | engine-default |
| 1024-18446744073709551615| pending-reboot | dynamic | integer | Defines the maximum size of internal in-memory temporary tables created by the MEMORY storage engine and, as of Aurora 3.04, the TempTable storage engine when aurora_tmptable_enable_per_table_limit is ON. | True | tmp_table_size | engine-default |
+---------------------------+-----------------+------------+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+----------------------+------------------+
- 出力内容
許容値 (AllowedValues) | 適用方法 (ApplyMethod) | 適用タイプ (ApplyType) | データ型 (DataType) | 説明 (Description) | 変更可能か (IsModifiable) | パラメータ名 (ParameterName) | ソース (Source) |
---|---|---|---|---|---|---|---|
16384 - 1844674407370954752 | pending-reboot | dynamic | 整数 (integer) | MEMORY テーブルが成長できる最大サイズ。 | True | max_heap_table_size | engine-default |
1024 - 18446744073709551615 | pending-reboot | dynamic | 整数 (integer) | MEMORY ストレージエンジンによって作成される内部のインメモリ一時テーブルの最大サイズを定義する。Aurora 3.04 以降では、aurora_tmptable_enable_per_table_limit が ON の場合、TempTable ストレージエンジンにも適用される。 |
True | tmp_table_size | engine-default |
デフォルトでは、サイズは16MB程度に設定されています。
2: カスタムDBパラメータグループの作成と変更
AWSでは、デフォルトのパラメータグループを直接編集することはできません。そのため、まずカスタムのパラメータグループを作成します。
2.1 パラメータグループファミリーを調べる
Auroraのエンジンバージョンに合ったファミリーを指定するため確認。
- 入力
aws rds describe-db-engine-versions \
--engine aurora-mysql \
--query 'DBEngineVersions[?EngineVersion==`8.0.mysql_aurora.3.09.0`].DBParameterGroupFamily' \
--output text
- 出力
aurora-mysql8.0
2.2 カスタムDBパラメータグループを作成する
上記で調べたファミリー名を指定して、新しいグループを作成。
- 入力
aws rds create-db-parameter-group \
--db-parameter-group-name "aurora-mysql80-temp-table-optimized" \
--db-parameter-group-family "aurora-mysql8.0" \
--description "Temporary table optimization for production cluster"
- 出力
{
"DBParameterGroup": {
"DBParameterGroupName": "aurora-mysql80-temp-table-optimized",
"DBParameterGroupFamily": "aurora-mysql8.0",
"Description": "Temporary table optimization for production cluster",
"DBParameterGroupArn": "arn:aws:rds:ap-northeast-1:123456789012:pg:aurora-mysql80-temp-table-optimized"
}
}
2.3 パラメータを変更する
作成したカスタムグループのパラメータを、問題解決のために変更します。ここでは一時テーブルの上限サイズ(作業スペース)を16MBから256MBへと拡張します。これにより、今までスペース不足で失敗していた複雑なクエリも正常に完了できるようになり、クエリの滞留とそれに伴うCPU高騰が解決されます。
- 入力
# tmp_table_sizeを256MBに設定
aws rds modify-db-parameter-group \
--db-parameter-group-name "aurora-mysql80-temp-table-optimized" \
--parameters "ParameterName=tmp_table_size,ParameterValue=268435456,ApplyMethod=pending-reboot"
# max_heap_table_sizeを256MBに設定
aws rds modify-db-parameter-group \
--db-parameter-group-name "aurora-mysql80-temp-table-optimized" \
--parameters "ParameterName=max_heap_table_size,ParameterValue=268435456,ApplyMethod=pending-reboot"
# (推奨) MySQL 8.0に最適化されたメモリ内一時テーブルエンジンを指定
aws rds modify-db-parameter-group \
--db-parameter-group-name "aurora-mysql80-temp-table-optimized" \
--parameters "ParameterName=internal_tmp_mem_storage_engine,ParameterValue=TempTable,ApplyMethod=pending-reboot"
ApplyMethod=pending-reboot
は、この変更を有効にするには再起動が必要であることを明示します。
--parameters オプションを複数指定することで、1つのコマンドにまとめることもできます。
aws rds modify-db-parameter-group \
--db-parameter-group-name "aurora-mysql80-temp-table-optimized" \
--parameters \
"ParameterName=tmp_table_size,ParameterValue=268435456,ApplyMethod=pending-reboot" \
"ParameterName=max_heap_table_size,ParameterValue=268435456,ApplyMethod=pending-reboot" \
"ParameterName=internal_tmp_mem_storage_engine,ParameterValue=TempTable,ApplyMethod=pending-reboot"
3: DBインスタンスに適用
パラメータの準備ができたら、DBインスタンスに適用します。--no-apply-immediately
オプションを指定することで、次のメンテナンスウィンドウまで適用(と再起動)を保留し、即時影響が出るのを防ぎます。
メンテナンスウィンドウになると、パラメータグループの適用とインスタンスの再起動が自動的に行われます。
- 入力
# 読み取りレプリカ1への適用
aws rds modify-db-instance \
--db-instance-identifier my-aurora-instance-1 \
--db-parameter-group-name "aurora-mysql80-temp-table-optimized" \
--no-apply-immediately
# 読み取りレプリカ2への適用
aws rds modify-db-instance \
--db-instance-identifier my-aurora-instance-2 \
--db-parameter-group-name "aurora-mysql80-temp-table-optimized" \
--no-apply-immediately
レスポンスとして対象インスタンスの現在の状態が返ってきます。
4: 適用後の確認と監視
再起動後、設定が正しく反映されたかを確認します。
4.1 パラメータ適用を確認する
MySQLクライアントでデータベースに接続し、以下のSQLを実行してグローバル変数が変更されていることを確認。
- 入力
SELECT
@@tmp_table_size/1024/1024 as tmp_table_size_mb,
@@max_heap_table_size/1024/1024 as max_heap_table_size_mb,
@@internal_tmp_mem_storage_engine as storage_engine;
- 出力
+-------------------+------------------------+----------------+
| tmp_table_size_mb | max_heap_table_size_mb | storage_engine |
+-------------------+------------------------+----------------+
| 256.00000000 | 256.00000000 | TempTable |
+-------------------+------------------------+----------------+
1 row in set (0.000 sec)
万が一のために:ロールバック手順
もし予期せぬ問題が発生した場合、すぐに元の状態に戻せるようにしておくことが重要です。元のパラメータグループを即座に適用し、インスタンスを再起動します。
- 入力
# <original-parameter-group-name>はSTEP1で確認した名前に置き換える
aws rds modify-db-instance \
--db-instance-identifier my-aurora-instance-1 \
--db-parameter-group-name <original-parameter-group-name> \
--apply-immediately
aws rds modify-db-instance \
--db-instance-identifier my-aurora-instance-2 \
--db-parameter-group-name <original-parameter-group-name> \
--apply-immediately
# 即座にリブート
aws rds reboot-db-instance --db-instance-identifier my-aurora-instance-1
aws rds reboot-db-instance --db-instance-identifier my-aurora-instance-2
期待される効果
このパラメータのチューニングにより、以下のような改善が期待できます。
- RDS CPU使用率: 99%+ → 80%以下に正常化
- ALB 5XXエラー数: 数百件/5分 → 10件以下に削減
- ALB平均応答時間: 2〜3秒 → 0.5秒以下に改善
- 原因:
table is full
エラーの解消
まとめ
今回は、Aurora MySQLのパフォーマンス問題に対して、AWS CloudShellを用いたDBパラメータの調整という解決策を手順に沿って解説しました。重要なのは、現象(CPU高騰)の裏にある原因(一時テーブル枯渇)をエラーログから突き止め、安全に設定変更を行うことです。
この記事で紹介した調査プロセスと具体的な解決策が、同様の問題に直面しているAWS運用担当者や開発者の助けとなれば幸いです。
参考
公式ドキュメント:
Amazon RDS の DB パラメータグループのパラメータの変更
MySQL 8.0 リファレンスマニュアル / 代替ストレージエンジン / MEMORY ストレージエンジン
アノテーション株式会社について
アノテーション株式会社はクラスメソッドグループのオペレーション専門特化企業です。サポート・運用・開発保守・情シス・バックオフィスの専門チームが、最新 IT テクノロジー、高い技術力、蓄積されたノウハウをフル活用し、お客様の課題解決を行っています。当社は様々な職種でメンバーを募集しています。「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、アノテーション株式会社 採用サイトをぜひご覧ください。