FlaskとSQLAlchemyを使っててMySQL server has gone awayってなる
flaskとsqlalchemyでapiを実装し、そのapiに対して一度リクエストしてからmysqlのwaittime_outが過ぎると
OperationalError: (OperationalError) (2006, 'MySQL server has gone away')
というエラーが出てしまい、うまく通信が出来なかった。
ちなみに、androidのvolleyを使ったリクエストです。
解決策
- wait_timeを長くする
- 上記のエラーが出る頻度は減るが、根本的な解決ではないし、mysqlの最大接続数を超えてしまう危険性がある
- よって却下
- キャッシュのtimeoutを長くする
- ごまかせるが、やはり根本的な解決ではない
- sqlalchemyとflaskを何とかする
- これしかない(?)
やったこと
色々調べながら手当たり次第にやったので、どれが効果あったのかいまいちわかってません...。
とりあえずやったことを列挙
1. sqlalchemyのcraete_engineの設定をいじる
参考:
(古いけど日本語) http://omake.accense.com/static/doc-ja/sqlalchemy/reference/sqlalchemy/pooling.html
(新しいけど英語) http://docs.sqlalchemy.org/en/latest/core/pooling.html
engine = create_engine("mysql://{user}:{passwd}@{host}/{db}"\ .format(user=user, passwd=passwd, host=host, db=db),\ encoding="utf-8", echo=False, pool_size=15, pool_recycle=3600,\ max_overflow=0, echo_pool=True)
2. sqlalchemyのsessionの作り方を変える
参考:
(古いけど日本語) http://omake.accense.com/static/doc-ja/sqlalchemy/session.html
(新しいけど英語) http://docs.sqlalchemy.org/en/rel_0_9/orm/session.html
from sqlalchmy.orm import sessionmaker, scoped_session Session = scoped_session(sessionmaker(\ autocommit=False, autoflush=False, bind=engine)) # session = Session()として使う
3. sessionを毎回commitする
参考:見失った
hoge = session.query(Table).all()#selectする session.commit() session.close()
4. flaskのappをいじる
参考:http://flask.pocoo.org/docs/patterns/sqlalchemy/
app = Flask("app_name") @app.teardown_appcontext def shutdown_session(exception=None): Session.remove()
Sessionが使えなくなっちゃうのでやめたほうがいいです多分。
5. mysqlserverにpingを送ってプロセスを起こす
参考:http://docs.sqlalchemy.org/en/latest/core/pooling.html
from sqlalchemy import exc from sqlalchemy import event from sqlalchemy.pool import Pool @event.listens_for(Pool, "checkout") def ping_connection(dbapi_connection, connection_record, connection_proxy): cursor = dbapi_connection.cursor() try: cursor.execute("SELECT 1") except: # optional - dispose the whole pool # instead of invalidating one at a time # connection_proxy._pool.dispose() # raise DisconnectionError - pool will try # connecting again up to three times before raising. raise exc.DisconnectionError() cursor.close()
これが効いたかも?
mysql
備忘録的
設定値をみる
show variables; # like "%timeout";
ってやれば設定値がみれる
timeout関係がみたければlikeでみる
また、これだとセッション値がみれて、(/etc/my.cnfで)設定した値を確認するには
show global variables;
とする
コンソールから変更するには
set session wait_timeout = 15; set global wait_timeout = 15;
とでもすればOK
globalの方は権限が必要っぽいですが