予想以上のストレージを使用している Amazon RDS MySQL DB インスタンスの問題を解決する方法を教えてください。

最終更新日: 2018 年 12 月 28 日

MySQL 上の Amazon Relational Database Service (Amazon RDS) データベースインスタンスが予想以上のストレージを使用しています。このような問題が発生しているのはなぜですか? ディスクストレージはどのように最適化できますか?

解決方法

FreeStorageSpace Amazon CloudWatch メトリックを使って RDS DB インスタンス用に利用できるストレージ容量を監視できますが、このメトリックは DB インスタンスがどのようにストレージを消費しているかは説明しません。

以下の戦略を使ってストレージ容量を解放します。

OPTIMIZE TABLE を実行する

テーブルによって消費される容量には、アクティブに使用されていないにもかかわらず、テーブルに割り当てられているものがあります。innodb_file_per_table が有効化されていると (これはデフォルトで有効化されています)、OPTIMIZE TABLE を使ってその容量を解放できます。詳細については、OPTIMIZE TABLE に関する MySQL ドキュメントを参照してください。 

フラグメンテーションをチェックするには、以下のようなクエリを実行します。

SELECT
	table_name,
	data_length,
	max_data_length,
	index_length,
	data_free
FROM
	information_schema.tables 
WHERE table_schema='schema_name'
;

data_free 列が、テーブルに割り当てられた空き容量で、アクティブに使用されていないものの量を表示します。テーブルが Amazon RDS のデフォルト innodb_file_per_table 構成設定に従って個別の表領域に作成されている場合、OPTIMIZE TABLE を使ってこの容量を解放できる可能性があります。 詳細については、innodb_file_per_table に関する MySQL ドキュメントを参照してください。

アプリケーションテーブルのストレージを削減する

DB インスタンス上のアプリケーションテーブルによって使用されているストレージの量を確認するには、以下のようなクエリを実行します。

SELECT 
	table_schema,
	SUM(data_length + index_length + data_free)/1024/1024 AS total_mb,
	SUM(data_length)/1024/1024 AS data_mb,
	SUM(index_length)/1024/1024 AS index_mb,
	SUM(data_free)/1024/1024 AS free_mb,
	COUNT(*) AS tables,
	CURDATE() AS today 
FROM 
	information_schema.tables
	GROUP BY table_schema
	ORDER BY 2 DESC
;

DB インスタンスにある最大のアプリケーションテーブルを見つけるには、以下のようなクエリを実行します。

SELECT 
	table_schema,
	table_name,
	(data_length + index_length + data_free)/1024/1024 AS total_mb,
	(data_length)/1024/1024 AS data_mb,
	(index_length)/1024/1024 AS index_mb,
	(data_free)/1024/1024 AS free_mb,
	CURDATE() AS today
FROM 
	information_schema.tables
	ORDER BY 3 DESC
;

注意: データベースに 768 バイトより長い可変長列を持つテーブルが含まれている場合 (例えば、BLOB、TEXT、VARCHAR、または VARBINARY)、個々のデータベースとテーブルが使用したストレージの総容量は計算できません。

バイナリログのストレージを削減する

リードレプリカの追加は、マスターインスタンスのバイナリログが追加のストレージを使用する原因になります。マスターインスタンス上のバイナリログが使用しているストレージ容量を確認するには、BinLogDiskUsage CloudWatch メトリックをチェックします。大きな増加は、ひとつ、または複数のリードレプリカが同期化されていないことを示す場合があります。詳細については、「MySQL バイナリログにアクセスする」を参照してください。

一般ログとスロークエリログのストレージを削減または無効化する

一般ログとスロークエリログのパラメータの有効化は、DB インスタンスがこれらのログとそのバックアップの保存を開始する原因になります。これらのファイルのローテーションを行い、ディスク使用量を制御するには、mysql.rds_rotate_general_log および mysql.rds_rotate_slow_log を参照してください。

注意: パフォーマンスとディスク使用量の問題が発生する可能性を防ぐため、一般ログとスロークエリログをトラブルシューティングのためにアクティブに使用していないときは、それらを無効化してください。

InnoDB のシステム表領域サイズの管理または削減

システム表領域には、InnoDB のデータディクショナリーと undo 容量が含まれており、最小サイズは 10 MB です。容量が割り当てられた後、ファイルは常に少なくともこのサイズになりますが、長時間に及ぶトランザクションでは、利用可能なストレージがより多く消費される場合があります。

Amazon RDS はデフォルトで innodb_file_per_table1 に設定します。これは各表領域のデータが表領域独自の .ibd ファイルに保存されることを意味します。関連するテーブルについて再利用可能としてマークされた容量を回復するには、OPTIMIZE TABLE コマンドを使ってテーブルの表領域ファイルごとにサイズを変更するか、テーブルをドロップします。

Innodb_file_per_table0 に設定されている場合、すべてのテーブルが同様にシステム表領域に割り当てられます。テーブルまたはインデックスをドロップする、またはシステム表領域に割り当てられたテーブルからデータを削除または切り捨てると、以前占有されていた容量が再利用可能としてマークされます。ただし、このコマンドはファイルシステムに容量を解放しません。

インプレースでシステム表領域を縮小することは不可能なので、現在のデータベースのデータをエクスポートしてから、そのデータを新しいインスタンスにインポートします。ダウンタイムを短縮するには、新しい MySQL インスタンスをソース Amazon RDS マスターインスタンスの従属インスタンスとして設定します。従属インスタンスがソース Amazon RDS マスターインスタンスと同期化されたら、新しいインスタンスに切り替えます。手動レプリケーションの詳細については、Amazon RDS の外部で実行される MySQL または MariaDB インスタンスとの レプリケーション

注意: スナップショットから復元、またはリードレプリカを作成しても、システム表領域からの容量の回復には役立ちません。これは、どちらの方法も、システム表領域が含まれるソースインスタンスストレージボリュームのスナップショットを使用するためです。