Amazon RDS for MySQL または MariaDB インスタンスがストレージが満杯と表示されているのはなぜですか?

最終更新日: 2021 年 9 月 8 日

MySQL 用の Amazon Relational Database Service (Amazon RDS) または MariaDB インスタンスが、ストレージが満杯と表示されています。これが起こっているのはなぜですか。また、DB インスタンスでストレージを使用しているものを表示するにはどうすればよいですか?

簡単な説明

ストレージが満杯になる問題をトラブルシューティングするには、まず DB インスタンスで使用されている合計容量を分析する必要があります。DB インスタンスの容量は次の用途で使用されます。

  • ユーザーが作成したデータベース
  • 一時テーブル
  • バイナリログまたは MySQL スタンバイインスタンスのリレーログ (リードレプリカを使用する場合)
  • InnoDB テーブルスペース
  • 一般ログ、スロークエリーログ、エラーログ

ストレージ容量を使用している内容を特定すると、ストレージ領域を再利用できます。次に、再び容量が不足することがないように FreeStorageSpace のメトリクスをモニタリングします。

注: 使用可能なストレージに急激な減少が見られた場合には、SHOW FULL PROCESSLIST コマンドを実行し、DB インスタンスレベルで継続的にクエリを確認します。SHOW FULL PROCESSLIST コマンドは、すべてのアクティブな接続と、各接続によって実行されるクエリに関する情報を提供します。長期間アクティブになっているトランザクションを表示するには、INFORMATION_SCHEMA.INNODB_TRX または SHOW ENGINE INNODB STATUS のコマンドを実行します。その後、出力を確認します。

解決方法

DB インスタンス (ユーザー作成データベース) で使用されている合計容量を分析する

各ユーザーが作成したデータベースのサイズを確認するには、次のクエリを実行します。

mysql> SELECT table_schema, ROUND(SUM(data_length+index_length)/1024/1024/1024,2) "size in GB" FROM information_schema.tables GROUP BY 1 ORDER BY 2 DESC;

(DB インスタンス内の) 特定のデータベースの各テーブルのサイズを確認するには、次のクエリを実行します。

mysql>SELECT table_schema "DB Name", table_name,(data_length + index_length)/1024/1024/1024 AS "TableSizeinGB" from information_schema.tables where table_schema='database_name';

データベースレベルとテーブルレベルで完全な記憶域の詳細と断片化されたおおよその領域を取得するには、次のクエリを実行します。

mysql> SELECT table_schema AS "DB_NAME", SUM(size) "DB_SIZE", SUM(fragmented_space) APPROXIMATED_FRAGMENTED_SPACE_GB FROM (SELECT table_schema, table_name, ROUND((data_length+index_length+data_free)/1024/1024/1024,2) AS size, ROUND((data_length - (AVG_ROW_LENGTH*TABLE_ROWS))/1024/1024/1024,2)
    AS fragmented_space FROM information_schema.tables WHERE table_type='BASE TABLE' AND table_schema NOT IN ('performance_schema', 'mysql', 'information_schema') ) AS TEMP GROUP BY DB_NAME ORDER BY APPROXIMATED_FRAGMENTED_SPACE_GB DESC;

mysql> SELECT table_schema DB_NAME, table_name TABLE_NAME, ROUND((data_length+index_length+data_free)/1024/1024/1024,2) SIZE_GB, ROUND((data_length - (AVG_ROW_LENGTH*TABLE_ROWS))/1024/1024/1024,2) APPROXIMATED_FRAGMENTED_SPACE_GB from information_schema.tables
    WHERE table_type='BASE TABLE' AND table_schema NOT IN ('performance_schema', 'mysql', 'information_schema') ORDER BY APPROXIMATED_FRAGMENTED_SPACE_GB DESC;

これら 2 つのクエリから取得したデータベースのサイズを記録し、Amazon RDS の Amazon CloudWatch メトリクスと比較します。その後、データ使用量が原因でフルストレージが発生しているかどうかを確認できます。

一時テーブル

InnoDB ユーザー作成一時テーブルとディスク上の内部一時テーブルは、 ibtmp1 という名前の一時テーブルスペースファイルに作成されます。一時テーブルスペースファイルが MySQL データディレクトリの ibtmp2 に拡張されることもあります。

ヒント: MySQL 5.7 以降では、一時テーブル (ibtmp1) が過剰にストレージ領域を使用すると、DB インスタンスを再起動して領域を解放します。

オンライン DDL 操作では、次の一時ログファイルが使用されることがあります。

  • 同時DMLの記録
  • インデックスの作成時に一時ソートファイルを作成する
  • テーブルの再構築時に一時中間テーブルファイルを作成する (一時テーブルがストレージを占有できるようにするため)

注:InnoDB テーブルスペースのファイルサイズは、MySQL バージョン 5.7 以降、または MySQL 8.0 以降を使用してのみ照会できます。

InnoDB の一時テーブルスペースを見つけるには、次のクエリを実行します。

mysql> SELECT file_name, tablespace_name, table_name, engine, index_length, total_extents, extent_size from information_schema.files WHERE file_name LIKE '%ibtmp%';

グローバル一時テーブルスペースデータファイルが占有しているディスク領域を再利用するには、MySQL サーバーを再起動するか、DB インスタンスを再起動します。詳細については、MySQL ウェブサイトの「一時テーブルスペース」を参照してください。

InnoDB テーブルスペース

MySQL が内部一時テーブルを作成し、介入中のクエリがあるため、削除できないこともあります。これらの一時テーブルは information_schema 内の「tables」には含まれません。詳細については、MySQL ウェブサイトの「MySQL での内部一時テーブルの使用」を参照してください。

次のクエリを実行して、これらの内部一時テーブルを見つけます。

mysql> SELECT * FROM information_schema.innodb_sys_tables WHERE name LIKE '%#%';

InnoDB システムテーブルスペースは InnoDB データディクショナリのストレージ領域です。データディクショナリとともに、ダブルライトバッファ、変更バッファ、元に戻すログも InnoDB システムテーブルスペースに存在します。さらに、テーブルが (テーブルごとのファイルまたは一般テーブルスペースではなく) システムテーブルスペースに作成されている場合は、テーブルスペースにインデックスとテーブルデータが含まれる場合があります。

次のクエリを実行し、InnoDB システムのテーブルスペースを見つけます。

mysql> SELECT file_name, tablespace_name, table_name, engine, index_length, total_extents, extent_size from information_schema.files WHERE file_name LIKE '%ibdata%';

注:このクエリは MySQL バージョン 5.7 以降、または MySQL 8.0 以降で実行されます。

システムテーブルスペースのサイズを増やした後は、それを減らすことはできません。ただし、すべての InnoDB テーブルをダンプし、そのテーブルを新しい MySQL DB インスタンスにインポートすることはできます。ラージシステムテーブルスペースを回避するには、テーブルごとのファイルテーブルスペースの使用を検討してください。詳細については、MySQL ウェブサイトの「テーブルごとのファイルに対するテーブルスペース」を参照してください。

InnoDB_FILE_PER_TABLE を有効にすると、各テーブルは独自のテーブルスペースファイルにデータとインデックスを格納します。そのテーブルで OPTIMIZE TABLE を実行すると、(データベースとテーブルの断片化から)領域を再利用することができます。OPTIMIZE TABLE コマンドは、テーブルの新しい空のコピーを作成します。次に、古いテーブルのデータが 1 行ずつ新しいテーブルにコピーされます。このプロセスでは、新しい.ibd 表領域が作成され、領域が再利用されます。このプロセスの詳細については、MySQL ウェブサイトの「OPTIMIZE TABLE ステートメント」を参照してください。

重要: OPTIMIZE TABLE コマンドは COPY アルゴリズムを使用して、元のテーブルと同じサイズの一時テーブルを作成します。このコマンドを実行する前に、使用可能なディスク領域が十分あることを確認してください。

テーブルを最適化するには、次のコマンド構文を実行します。

mysql> OPTIMIZE TABLE <tablename>;

または、次のコマンドを実行してテーブルを再構築できます。

mysql> ALTER TABLE <table_name> ENGINE=INNODB;

バイナリログ

Amazon RDS インスタンスで自動バックアップを有効にすると、DB インスタンスでもバイナリログが自動的に有効になります。これらのバイナリログはディスクに格納され、ストレージ容量を消費しますが、バイナリログの保持構成ごとにパージされます。インスタンスのデフォルトのバイナリログ保持値も「Null」に設定されています。これは、ファイルがすぐに削除されることを意味します。

ストレージ容量不足の問題を回避するには、Amazon RDS for MySQL で適切なバイナリログの保持期間を設定します。バイナリログが保持される時間数は、 mysql.rds_show_configuration コマンド構文で確認できます。

CALL mysql.rds_show_configuration;

この値を減らしてログの保存期間を短縮することで、ログが使用する領域量を減らすことも可能です。NULL 値は、可能な限り迅速にログを消去することを意味します。アクティブインスタンスのスタンバイインスタンスがある場合は、スタンバイインスタンスの RepliCalag メトリクスをモニタリングします。ReplicaLag メトリクスは、アクティブインスタンスでのバイナリログ処理中、またはスタンバイインスタンスのリレーログ処理中に発生した遅延を示します。

アクティブインスタンスのスタンバイインスタンスがある場合は、スタンバイインスタンスの RepliCalag メトリクスをモニタリングします。ReplicaLag メトリクスは、アクティブインスタンスでのバイナリログのパージとスタンバイインスタンスのリレーログの遅延を示します。パージまたはレプリケーションの問題がある場合、これらのバイナリログは時間の経過とともに蓄積され、追加のディスク容量を消費する可能性があります。インスタンスのバイナリログの数とファイルサイズを確認するには、 SHOW BINARY LOGS コマンドを使用します。詳細については、MySQL ウェブサイトの「SHOW BINARY LOGS ステートメント」を参照してください。

DB インスタンスがレプリケーションスタンバイインスタンスとして機能している場合、次のコマンドを使用して、リレーログ (Relay_Log_Space) の値を確認します。

SHOW SLAVE STATUS\G

MySQL ログ (一般ログ、スロークエリーログ、エラーログ)

Amazon RDS for MySQL には、データベースのモニタリングに使用できるログ (一般ログ、スロークエリログ、エラーログなど) が用意されています。エラーログはデフォルトで有効になっています。ただし、一般ログとスロークエリログは、RDS インスタンスのカスタムパラメータグループを使用して有効にできます。スロークエリログと一般ログを有効にすると、MySQL データベース内の slow_log テーブルと general_log テーブルに自動的に格納されます。スロークエリ、一般ログ(「FILE」タイプ)、エラーログのサイズを確認するには、データベースログファイルを表示してリストします

スロークエリログと一般ログのテーブルが過剰にストレージを使用している場合は、ログテーブルをマニュアルでローテーションして、 テーブルベースの MySQL ログを管理します。古いデータを完全に削除し、ディスク領域を再利用するには、次のコマンドを 2 回連続で呼び出します。
mysql> CALL mysql.rds_rotate_slow_log;
mysql> CALL mysql.rds_rotate_general_log;

注: テーブルからはログの正確なファイルサイズを知ることができません。そこで、パラメータを変更しますlog_output slow_loggeneral_log でのパラメータ値を、Table ではなく File にします。

また、Amazon CloudWatch を使用して Amazon RDS DB インスタンスをモニタリングすることもベストプラクティスですFreeStorageSpace メトリクスで CloudWatch アラームを設定すると、ストレージ容量が特定のしきい値を下回ったときにアラートを受信できます。最後に、Amazon CloudWatch アラームを設定して FreeStorageSpace メトリクスをモニタリングし、DB インスタンスの空き容量が低下したときに通知を受け取れるようにします。詳細については、Amazon RDS の空きストレージ容量をモニタリングしてストレージが満杯になる問題を防ぐための CloudWatch アラームを作成するにはどうすればよいですか?を参照してください。

また、 Amazon RDS ストレージのオートスケーリング機能を使用して、容量を自動的に管理することもできます。ストレージのオートスケーリングを使用すると、データベースストレージをマニュアルでスケールアップする必要はありません。Amazon RDS ストレージのオートスケーリングの詳細については、「Amazon RDS DB インスタンスのストレージの使用」を参照してください。