「Table is Full」エラーの理解
ERROR 1114 (HY000): The table 'session_cache' is full というエラーが表示されるのは、データベースにおける典型的な「ガス欠」の状態です。構文エラーや権限の問題とは異なり、これはハードウェアのリソース制限に達したことを意味します。MySQLは、物理ハードウェアまたは特定の設定ファイルにおいて上限に達したことを伝えています。
このエラーは通常、大量の INSERT 操作中や、複雑なクエリが巨大な内部テンポラリテーブルを生成したときに発生します。修正方法は、テーブルのエンジンが InnoDB か MEMORY かによって完全に異なります。
テーブルエンジンの特定
設定を変更する前に、対象のテーブルがどのストレージエンジンを使用しているか確認してください。MySQLシェルで以下のコマンドを実行します:
SHOW TABLE STATUS WHERE Name = 'session_cache';
Engine カラムを確認してください。InnoDB の場合はディスク容量不足かテーブルスペースの制限に達しており、MEMORY の場合は割り当てられたRAMを使い果たしています。
シナリオ 1: InnoDBテーブルの修復
InnoDBがこの制限に達した場合、ほとんどの場合はストレージドライブにデータを1バイトも書き込めない状態であることを意味します。
ステップ 1: 物理ストレージの確認
最も多い原因はハードドライブの空き容量不足です。Linuxターミナルからすぐにディスク使用量を確認してください:
df -h
データパーティション(多くの場合 /var/lib/mysql)の使用率が98%または100%に達している場合は、ファイルを削除する必要があります。容量を圧迫している巨大なスロークエリログや、放置されたバックアップファイルを探してください。例えば、50GBの slow_query.log は小規模なサーバーを簡単にクラッシュさせます:
sudo du -sh /var/log/*
sudo find /var/lib/mysql -name "*.log" -size +100M
ステップ 2: InnoDBテーブルスペース制限の拡張
200GBの空き容量があるにもかかわらずエラーが発生する場合はどうすればよいでしょうか? その場合、my.cnf(または my.ini)でデータファイルのサイズに上限が設定されている可能性があります。innodb_data_file_path ディレクティブを探してください。
以下のように、成長を特定のサイズ(例:2GB)に制限している行が見つかるかもしれません:
innodb_data_file_path = ibdata1:10M:autoextend:max:2000M
ibdata1 が2000MBに達すると、MySQLは書き込みを停止します。これを修正するには、制限をより大きな値(10G など)に増やすか、上限を完全に削除してディスク容量に合わせて成長できるようにします:
# :max:2000M サフィックスを削除して無制限の成長を許可する
innodb_data_file_path = ibdata1:10M:autoextend
注意:これらの変更を適用するには、MySQLサービスを再起動する必要があります。
ステップ 3: テンポラリディレクトリのクリア
MySQLは大規模なソート操作に /tmp をよく使用します。もし /tmp がわずか512MBの小さなパーティションにマウントされている場合、複雑なクエリはエラー1114で失敗します。設定を編集して、これらのテンポラリファイルをより大きなパーティションにリダイレクトできます:
[mysqld]
tmpdir = /home/mysql_tmp
シナリオ 2: MEMORYテーブルの修復
MEMORYテーブルは完全にRAM上に存在します。SSDの空き容量は関係なく、事前に割り当てられたメモリ予算のみが重要です。
ステップ 1: RAM制限の確認
現在のヒープおよびテンポラリテーブルの制限をクエリで確認します:
SHOW VARIABLES LIKE 'max_heap_table_size';
SHOW VARIABLES LIKE 'tmp_table_size';
ステップ 2: メモリ予算の増額
session_cache テーブルがデフォルトの16MBを超えて成長してしまった場合、動的に512MBや1GBに引き上げることができます:
SET GLOBAL tmp_table_size = 536870912; -- 512MB
SET GLOBAL max_heap_table_size = 536870912; -- 512MB
再起動後もこの設定を維持するには、my.cnf の [mysqld] セクションに以下の行を追加します:
[mysqld]
tmp_table_size = 512M
max_heap_table_size = 512M
重要: 既存のMEMORYテーブルは、これらの変数を変更しても自動的にはリサイズされません。新しい制限を有効にするには、テーブルを「リフレッシュ」する必要があります:
ALTER TABLE session_cache ENGINE=MEMORY;
解決策の検証
変更を適用した後、以下の3つのチェックで修正を確認してください:
- 書き込みの再試行: 先ほど失敗した
INSERTまたはUPDATEを試行します。 - 成長の監視:
SHOW TABLE STATUS LIKE 'session_cache';を使用して、Data_lengthが以前の制限を超えて増加していることを確認します。 - システムヘルスの監視:
htopを実行し、MySQLのヒープ制限を増やした後にOSのRAMが不足していないか確認します。
予防策
- File-Per-Tableの使用:
innodb_file_per_tableを有効にします。これにより、ibdata1が巨大で管理不可能なバイナリの塊になるのを防げます。 - アラートの自動化: ディスク使用率が85%に達したときに通知が来るよう、cronジョブや監視ツール(Zabbixなど)を設定します。
- セッションのパージ:
session_cacheのようなテーブルについては、期限切れデータを削除するクリーンアップスクリプトを毎日実行します:DELETE FROM session_cache WHERE expires_at < NOW(); - InnoDBへの切り替え: MEMORYテーブルが頻繁にRAM容量を超える場合は、InnoDBに変換することを検討してください。現代のNVMe SSDであれば、ディスクベースのストレージによる安定性に比べれば、パフォーマンスへの影響は無視できる程度です。

