問題現象
MySQLクライアント接続時に操作がない状態が続くと、次のエラーが発生することがあります:
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
または
ERROR 2013 (HY000): Lost connection to MySQL server during query
これらのエラーは接続が切断されたことを示し、再接続が必要です。このタイムアウト時間はMySQLの特定のパラメータによって制御されます。
パラメータ定義
MySQL 5.7ドキュメントに基づく定義:
- wait_timeout (デフォルト: 28800秒)
非対話型接続において、サーバーがアクティビティを待機する時間
- interactive_timeout (デフォルト: 28800秒)
対話型接続において、サーバーがアクティビティを待機する時間
検証実験
interactive_timeout変更時の挙動
SET GLOBAL interactive_timeout = 10;
SELECT @@global.wait_timeout, @@session.wait_timeout,
@@global.interactive_timeout, @@session.interactive_timeout;
対話型接続(mysqlクライアント)での挙動:
SELECT ... -- 10秒後に接続切断が発生
ERROR 2006 (HY000): MySQL server has gone away
非対話型接続(Pythonアプリケーション)の挙動:
def execute_query():
while True:
max_id = session.query(func.max(Table.id)).first()
logger.info(f'Current max ID: {max_id}')
session.commit()
time.sleep(15)
interactive_timeoutの変更は非対話型接続に影響しません。
wait_timeout変更時の挙動
SET GLOBAL wait_timeout = 10;
SET GLOBAL interactive_timeout = 30;
対話型接続での挙動:
SELECT ... -- 30秒後に接続切断
ERROR 2006 (HY000): MySQL server has gone away
非対話型接続での挙動:
def connection_test():
while True:
try:
result = conn.execute("SELECT @@wait_timeout, NOW()")
print(result.fetchall())
except Exception as e:
print(f'Error occurred: {e}')
time.sleep(15)
[(10, datetime.datetime(2024, 7, 25, 16, 14, 13))]
Error occurred: (pymysql.err.OperationalError) (2013, 'Lost connection...')
結論
- 対話型接続:interactive_timeoutパラメータで制御
- 非対話型接続:wait_timeoutパラメータで制御
補足:TCP Keepaliveの影響
OSレベルのTCP keepalive設定(例:tcp_keepalive_time=15)はMySQLの接続タイムアウトに影響しません:
# クライアント側設定
echo 15 > /proc/sys/net/ipv4/tcp_keepalive_time
# MySQL設定
SET GLOBAL wait_timeout = 20;
パケットキャプチャ結果より、TCP keepaliveパケットが送信されても、MySQLサーバーは20秒で接続を切断します。