- MySQL
MySQL server has gone awayの原因と直し方|2006
(2006, "MySQL server has gone away") は、アプリが MySQL に問い合わせを送ろうとしたとき、接続がすでに切れていたときのエラーです。 よくある原因は次の2つです。
| 原因 | 起きる場面 | 直し方 |
|---|---|---|
| ① 送ったデータが大きすぎる(max_allowed_packet) | 大きな画像・JSON・まとめての INSERT | max_allowed_packet を上げる、または 小分けにして送る |
| ② 長い時間、接続を使わなかった(wait_timeout) | 夜間に止まっていた Web アプリ、長いバッチの途中 | 接続プールの pool_pre_ping・pool_recycle、使う直前に接続する |
同じ原因でも、クライアント(ドライバ)によって、エラーの番号が 2006・2013・1153・4031 と変わりました。 番号だけで原因を決めず、「何をしたときに出たか」で切り分けます。
確認環境:MySQL 8.0.46、PyMySQL 2.2.8、mysql-connector-python 26.7.0、SQLAlchemy 2.1.4、mysql コマンド(クライアント)で再現しました(確認日 2026年10月11日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「MySQL server has gone awayの原因と直し方|2006」
原因① max_allowed_packet を超えるデータを送った
max_allowed_packet を 1MB にして、2MB の文字列を送りました。
| クライアント | 1回目(大きなデータ) | 2回目(SELECT 1) |
|---|---|---|
| PyMySQL | (2006, "MySQL server has gone away (BrokenPipeError(32, 'Broken pipe'))") |
InterfaceError (0, '') |
| mysql-connector-python | 1153 (08S01): Got a packet bigger than 'max_allowed_packet' bytes |
2013 (HY000): Lost connection to MySQL server during query |
| mysql コマンド(SQL ファイルを流し込み) | ERROR 1153 (08S01): Got a packet bigger than 'max_allowed_packet' bytes |
ERROR 2013 (HY000): Lost connection to MySQL server during query |
MySQL のマニュアルでは、サーバーは大きすぎるパケットを受け取ると、クライアントに問題があるとみなして接続を閉じると説明されています。PyMySQL では、その結果が MySQL server has gone away として表示されました。
直し方
SHOW VARIABLES LIKE 'max_allowed_packet'; -- 確認環境の既定は 67108864(64MB)
SET GLOBAL max_allowed_packet = 134217728; -- 128MB
確認環境では、SET GLOBAL のあとも、すでにつないでいた接続の @@session.max_allowed_packet は変わりませんでした。 アプリの接続(接続プール)をつなぎ直してから試します。
| 直し方 | 内容 |
|---|---|
| サーバーの max_allowed_packet を上げる | 設定ファイル(my.cnf の [mysqld])に書くと、再起動後も残る |
| まとめての INSERT を小分けにする | 1万行を1文で送らず、1,000行ずつ送る(マニュアルでも、1回に送る行を減らす方法が挙げられている) |
| 大きなファイルは DB に入れない | 画像・PDF はストレージに置き、DB にはパスを保存 |
マニュアルでは、クライアント側の上限も上げる必要がある場合があると説明されています。クラウドの DB は、各サービスの設定の方法で変更します。
原因② wait_timeout より長く、接続を使わなかった
wait_timeout を 3 秒にして、接続してから 5 秒待ってから問い合わせました。
| クライアント | 結果 |
|---|---|
| PyMySQL | (2013, 'Lost connection to MySQL server during query') |
| mysql-connector-python | 4031 (HY000): The client was disconnected by the server because of inactivity. See wait_timeout and interactive_timeout for configuring this behavior. |
| mysql コマンド | ERROR 4031 (HY000): The client was disconnected ... |
マニュアルでは、サーバーは既定で、何もしないまま 8 時間たった接続を閉じると説明されています(確認環境の wait_timeout も 28800 秒 = 8 時間)。Web アプリを夜間そのままにし、朝の最初のアクセスでエラーになるのは、この形です。
4031 のメッセージには、wait_timeout が原因だと書かれています。 2006・2013 は、ほかの原因(サーバーの再起動・ネットワーク)でも出るので、出た時刻と、その前にどれだけ接続が使われていなかったかを確かめます。
直し方:接続プールで、使う前に確かめる
SQLAlchemy で、wait_timeout を 3 秒にして試しました。
engine = create_engine(url, pool_pre_ping=True) # 使う前に接続を確かめる
# または
engine = create_engine(url, pool_recycle=3600) # 1時間たった接続は作り直す
| create_engine の設定 | 5 秒待ってから接続を取り出した結果 |
|---|---|
| 指定なし | OperationalError (2013, 'Lost connection to MySQL server during query') |
pool_pre_ping=True |
成功(切れた接続を捨てて、つなぎ直した) |
pool_recycle=2 |
成功(時間がたった接続を作り直した) |
SQLAlchemy の公式ドキュメントでは、pool_recycle は、一定時間で接続を閉じる MySQL のようなデータベースに向いていると説明されています。 pool_recycle は wait_timeout より短い秒数にします。
どちらも、接続を取り出すときに確かめるだけです。 ドキュメントにも、トランザクションの途中で切れた接続には効かないとあります。長い処理の途中で切れた場合は、処理をやり直す仕組みが必要です。
PyMySQL だけで使う場合
conn.ping(reconnect=True) # 切れていたら、つなぎ直す
確認環境では、ping(reconnect=True) のあと SELECT 1 が成功しました。ただし PyMySQL 2.2.8 では reconnect 引数は非推奨という警告(DeprecationWarning)が出ました(「再接続したいなら、新しい接続を作る」という内容)。新しく書くコードは、接続プールか、処理ごとに接続する形にします。
バッチ処理で起きやすい形
| 形 | 何が起きるか | 直し方 |
|---|---|---|
| 最初に接続し、重い集計(数時間)のあとで DB に書く | 集計の間に wait_timeout を超える | 書く直前に接続する |
| 1万行を1つの INSERT で送る | max_allowed_packet を超える | 1,000行ずつ送る |
| 親プロセスの接続を、子プロセスで使う | 接続が壊れる(マニュアルにも記載) | 子プロセスごとに接続する |
確認の手順(チェックリスト)
| 順番 | 確認すること | 方法 |
|---|---|---|
| 1 | 大きなデータを送った直後か | 送ったデータの大きさと max_allowed_packet を比べる |
| 2 | 長く使っていなかった接続か | エラーの時刻と、前回の利用時刻 |
| 3 | 4031 なら | wait_timeout が原因 |
| 4 | 接続プールの設定 | pool_pre_ping・pool_recycle |
| 5 | サーバーが再起動していないか | SHOW GLOBAL STATUS LIKE 'Uptime' |
| 6 | エラーログ | サーバーが落ちていないか |
よくある質問
Q. Java(JDBC)の Communications link failure と同じ原因ですか。 A. wait_timeout で切れた接続を使う、という原因は同じことがあります。関連記事の「Communications link failureの原因と直し方|MySQL」で扱っています。
Q. wait_timeout を大きくすれば解決しますか。 A. 切れにくくはなりますが、使われない接続がサーバーに残り続けます。アプリ側で、使う前に確かめる(pre_ping)か、時間がたった接続を作り直す(recycle)ほうが、サーバーの再起動やネットワークの切断にも対応できます。
まとめ
- 送ったデータが大きすぎる(max_allowed_packet)か、長く使わなかった(wait_timeout)のが主な原因
- クライアントによって、2006・2013・1153・4031 と番号が変わる
- 4031 は wait_timeout が原因とメッセージに書かれている
- SQLAlchemy は
pool_pre_ping=Trueかpool_recycleで直った - バッチは書く直前に接続、INSERT は小分けに
参考・出典
確認日はいずれも 2026年10月11日です。
- MySQL 8.0 Reference Manual「MySQL server has gone away」:https://dev.mysql.com/doc/refman/8.0/en/gone-away.html
- SQLAlchemy ドキュメント「Connection Pooling」:https://docs.sqlalchemy.org/en/20/core/pooling.html
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「MySQL server has gone awayの原因と直し方|2006」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。