問題の概要
ルーチンの INSERT を実行中、突然 MySQL が拒否反応を示しました。データベースは次のようなメッセージを返し、データの受け入れを拒否します。
ERROR 1526 (HY000): Table has no partition for value 2024
MySQL のパーティショニングを書類キャビネットに例えてみましょう。「2024」というラベルの付いた書類をファイリングしようとしても、フォルダが「2023」までしかない場合、システムはどこに置けばよいか分からなくなります。動的に拡張される標準的なテーブルとは異なり、パーティションテーブルは厳格です。すべての行には、RANGE または LIST ルールに基づいた定義済みの「格納先」が必要です。
発生原因
- 新年の不具合: 年ごとにパーティションを分割している場合、1月1日になって新しい年のパーティションを作成し忘れていたことに気づくケース。
- 範囲外の ID:
PARTITION BY RANGE (id)を使用して上限を 100,000 に設定していたが、自動インクリメント(auto-increment)の値が 100,001 に達した場合。 - 不足しているカテゴリ: リージョンごとに
PARTITION BY LISTを使用している場合(例: 1 は米国、2 は英国)、ユーザーが新しいリージョン(ID 3)のデータを送信した場合。
ステップ 1: ギャップを特定する
テーブルを修正する前に、境界がどこで終わっているかを正確に把握する必要があります。次のコマンドを実行して、テーブルの現在の構成を確認してください。
SHOW CREATE TABLE transactions;
より分かりやすく表示するには、information_schema をクエリします。これにより、現在許可されている正確な最大値が表示されます。
SELECT
PARTITION_NAME,
PARTITION_DESCRIPTION
FROM
information_schema.PARTITIONS
WHERE
TABLE_NAME = 'transactions'
AND TABLE_SCHEMA = 'finance_db';
もし PARTITION_DESCRIPTION が 2023 で止まっている場合、2024 年のデータは即座にエラーを引き起こします。
ステップ 2: 新しいパーティションを追加する
テーブルが RANGE パーティショニングを使用していて、「キャッチオール(すべてを受け入れる)」パーティションがない場合は、単に新しい範囲を追加できます。例えば、現在の最大パーティションが p2023(2024 未満)であるとします。2024 年に備えて次を実行します。
ALTER TABLE transactions
ADD PARTITION (PARTITION p2024 VALUES LESS THAN (2025));
注意: これは MAXVALUE パーティションがまだ定義されていない場合にのみ機能します。定義されている場合は、ステップ 4 に進んでください。
ステップ 3: MAXVALUE で将来に備える
毎月手動でパーティションを追加するのは、深夜の緊急呼び出しを招くようなものです。将来のクラッシュを防ぐために、「キャッチオール」パーティションを追加しましょう。これは、定義された範囲を超えるあらゆる値に対するセーフティネットとして機能します。
ALTER TABLE transactions
ADD PARTITION (PARTITION p_future VALUES LESS THAN MAXVALUE);
これで、もし 2026 年の値を持つ行が予定より早く届いても、アプリケーションを停止させることなく p_future に格納されます。
ステップ 4: MAXVALUE パーティションを分割する
すでに MAXVALUE パーティションがある場合、MySQL は ADD PARTITION の使用を許可しません。最後のパーティションは MAXVALUE である必要があるというエラーが表示されます。代わりに、REORGANIZE PARTITION を使用して、既存のキャッチオールから新しい範囲を「切り出す」必要があります。
p_max パーティションが現在 2023 年以降のすべてのデータを保持している場合、次のようにして 2024 年専用のスロットを作成します。
ALTER TABLE transactions
REORGANIZE PARTITION p_max INTO (
PARTITION p2024 VALUES LESS THAN (2025),
PARTITION p_max VALUES LESS THAN MAXVALUE
);
このコマンドは安全であり、既存のデータを保持したまま、基盤となるストレージを再配置します。
修正の確認方法
修正されたと思い込まず、次の 3 つのチェックを実行しましょう。
- スキーマの確認:
information_schemaのクエリを再実行して、新しいp2024エントリが表示されるか確認します。 挿入テスト: 先ほど失敗したクエリを手動で実行します:
INSERT INTO transactions (id, created_at) VALUES (550, '2024-02-10');
- **データの追跡:** 新しい行が実際にどのパーティションに保持されているかを確認します:
```
SELECT * FROM transactions PARTITION (p2024) WHERE id = 550;
メンテナンスのヒント
- 自動化: MySQL イベントスケジューラを使用して、月に一度ストアドプロシージャを実行します。これにより、必要になる前に翌月のパーティションを自動的に作成できます。
- 増加の監視:
AUTO_INCREMENTの値が最大パーティション範囲の 80% に達したときに通知が来るよう、Nagios や Zabbix でアラートを設定します。 - クリーンに保つ: パーティショニングはパフォーマンス向上に優れていますが、パーティション数が 1,000 を超えると、逆にクエリプランニングが遅くなる可能性があります。適切なバランスを心がけましょう。

