何が起きたのか
INSERTやLOAD DATA INFILEを実行中に — SQLダンプのインポート、BLOBの保存、大きなJSONペイロードの送信など — MySQLが以下のエラーを投げました:
ERROR 1153 (08S01): Got a packet bigger than 'max_allowed_packet' bytes
MySQLはクライアントとサーバー間のデータをパケットで送受信します。max_allowed_packet変数は1つのパケットの最大サイズを設定し、実質的に1つの行またはクエリのサイズを制限します。古いMySQLバージョンのデフォルトは4 MBですが、MySQL 8.0では64 MBに引き上げられました。いずれにせよ、データがこの上限を超えると、サーバーは操作全体を破棄します。
このエラーが発生しやすいケース:
- 大きな
BLOBやTEXTデータを含む.sqlダンプのインポート - Base64エンコードされた画像やPDFを
MEDIUMBLOB/LONGBLOBカラムに挿入 - ORMを通じて大きなJSONカラム値を送信
- あるサーバーで
mysqldumpを実行し、上限値が低い別のサーバーへリストア
デバッグ:現在の上限を確認する
何かを変更する前に、クライアントとサーバーの両方が実際に使用している値を確認しましょう。
-- mysqlクライアント内で実行
SHOW VARIABLES LIKE 'max_allowed_packet';
以下のような結果が返ってきます:
+--------------------------+---------+
| Variable_name | Value |
+--------------------------+---------+
| max_allowed_packet | 4194304 |
+--------------------------+---------+
この数値はバイト単位です。4194304 = 4 MBです。20 MBのBLOBを挿入しようとしている?これが原因です。
セッションレベルの値も確認しましょう — ランタイムで変更された場合、グローバルとセッションで値が異なることがあります:
SHOW SESSION VARIABLES LIKE 'max_allowed_packet';
解決策1:my.cnfでmax_allowed_packetを増やす(恒久的な修正)
本番環境では、これが正しい修正方法です。MySQLの設定ファイルを開きます — 正確なパスはディストリビューションによって異なります:
/etc/mysql/mysql.conf.d/mysqld.cnf(Ubuntu/Debian)/etc/my.cnf(CentOS/RHEL)/etc/mysql/my.cnf
[mysqld]セクションを追加または更新します:
[mysqld]
max_allowed_packet = 128M
次に[mysql]も更新してクライアントの上限を一致させます。不一致があると、サーバーが設定を無視しているように見える紛らわしいエラーが発生します:
[mysql]
max_allowed_packet = 128M
変更を反映させるためにMySQLを再起動します:
# Ubuntu/Debian
sudo systemctl restart mysql
# CentOS/RHEL
sudo systemctl restart mysqld
想定される最大ペイロードをカバーするサイズを選んでください。よく使われる値:64M、128M、256M。上限は1 GB(1G)です。
解決策2:動的に設定する(再起動不要)
今すぐ再起動できない場合 — 例えばライブサーバーのトラフィックピーク時など — 代わりにランタイムでグローバル値を変更できます。ただし、my.cnfも更新しない限り、次回の再起動でリセットされることに注意してください。
-- SUPERまたはSYSTEM_VARIABLES_ADMIN権限が必要
SET GLOBAL max_allowed_packet = 128 * 1024 * 1024; -- 128 MB
注意点として、変更は既に開いている接続には適用されません。このコマンドを実行した後、クライアントセッションを再接続してください。
解決策3:SQLダンプのインポート時にフラグを指定する
mysqlインポート中にエラーが発生した場合、コマンドラインでパケットサイズを直接設定できます — サーバーの設定変更は不要です:
mysql --max_allowed_packet=128M -u root -p your_database < dump.sql
これはそのセッションのみクライアント側の上限を引き上げます。サーバー側もパケットを受け入れる必要があるため、両側を制御できる場合、またはサーバーの上限がすでに十分に高い場合にのみ有効です。
解決策4:ダンプ時にも上限を引き上げる
mysqldump自体の実行中にエラーが発生することもあります — ダンプが既にサイズ超過のSQLステートメントを生成している場合です。同じ修正、同じフラグを使います:
mysqldump --max_allowed_packet=128M -u root -p your_database > dump.sql
修正を確認する
MySQLを再起動(またはSET GLOBALを実行して再接続)した後、新しい値が反映されたことを確認します:
SHOW GLOBAL VARIABLES LIKE 'max_allowed_packet';
128 MBに設定した場合、以下のように表示されるはずです:
+--------------------------+-----------+
| Variable_name | Value |
+--------------------------+-----------+
| max_allowed_packet | 134217728 |
+--------------------------+-----------+
134217728 = 128 × 1024 × 1024 = 128 MBです。失敗した操作を再試行してください。ダンプのインポートの場合:
mysql -u root -p your_database < dump.sql
echo "Exit code: $?"
終了コードが0なら成功です。
上限を引き上げても失敗する場合
変更を行った後でもつまずくことがある点がいくつかあります:
- **複数の設定ファイルが競合している:**MySQLは複数の場所から設定を読み込み、後から読み込まれたファイルが低い値で設定を上書きすることがあります。
mysql --verbose --help | grep -A 1 'Default options'を実行して、どのファイルがどの順番で読み込まれるかを確認してください。 - 開いている接続が古い値を保持している:
SET GLOBALは新しい接続にのみ影響します。コマンドを実行する前に既に開いていたセッションは古い上限を使い続けています — 切断して再接続してください。 - **ドライバー側の上限:**JDBC、Pythonの
mysqlclient、その他のコネクターには、接続文字列やドライバー設定に独自のmax_allowed_packet設定が組み込まれていることがあります。そちらも確認してください。 - データサイズに対してカラム型が合っていない:
BLOBの上限は65 KBです。MEDIUMBLOBは最大16 MBです。LONGBLOBは最大4 GBを扱えます。10 MBのデータを通常のBLOBカラムに格納しようとしている場合、パケットサイズを増やしても意味がありません — まずカラム型を変更する必要があります。
得られた教訓
max_allowed_packetは常に[mysqld]と[mysql]の両方に設定してください。サーバーとクライアントの上限が一致していないと、値が同期していないと気づくまでランダムに見えるエラーが発生します。- ファイルやバイナリデータを扱う新しいMySQLインスタンスをセットアップする際は、最初から
max_allowed_packetを少なくとも64Mに設定してください。4 MBのデフォルトは時代遅れで、最近のアプリのほとんどはいずれその壁にぶつかります。 - 設定ファイルを一覧表示する
mysql --verbose --helpのトリックは驚くほど使われていません。編集内容が実際に読み込まれているか、別のファイルに静かに上書きされていないかを確認する最速の方法です。 - 設定ファイルのフォーマット間でやり取りしたり構文の問題をトラブルシューティングする際は、ToolCraftのYAML ↔ JSONコンバーターにスニペットを貼り付けて構造を確認することがあります。アップロードは一切なく、すべてブラウザ内で処理されます。

