web-dev-qa-db-ja.com

頻繁に使用されないPython / Flask server with SQLAlchemy

Flask/SQLAlchemyが設定されていない場合、新しいデータベース接続を作成するにはどうすればよいですか?

頻繁にアクセスしないPython/FlaskサーバーはSQLAlchemyを使用します。サーバーがなくなりました」というエラーが表示されます。その後のページビューは問題ありませんが、この最初のエラーはプロには見えません。

私はこれを処理する正しい方法を知りたいです-この場合約4日間である「本当に長い時間を作る」のようなアドバイスは正しくないようです。データベース接続の欠如をテストし、必要に応じて作成するにはどうすればよいですか?

47
Ollie Glass

私は以前これで問題を抱えていましたが、それを処理する方法はセッションを維持しないことです。問題は、接続を長時間開いたままにしようとしていることです。代わりに、__init__.pyまたはどこにでもインポートするユーティリティパッケージ内:

from sqlalchemy.orm import scoped_session, sessionmaker
Session = scoped_session( sessionmaker() )

次に、エンジンとメタデータを一度セットアップします。これにより、接続/切断するたびに構成メカニズムをスキップできます。その後、次のようにdbを実行できます。

session = Session()
someObject = session.query( someMappedClass ).get( someId )
# use session like normal ...
session.close()

古いオブジェクトを保持し、セッションを開いたままにしたくない場合は、上記のパターンを使用して、次のように古いオブジェクトを再利用できます。

session = Session()
someObject = session.merge( someObject )
# more db stuff
session.close()

ポイントは、セッションを開き、作業を行い、セッションを終了することです。これにより、タイムアウトが非常によく回避されます。 .mergeおよび.addには多くのオプションがあり、デタッチされたオブジェクトに加えた変更を含めるか、dbから新しいデータを読み込むことができます。ドキュメントは非常に冗長ですが、探しているものがわかれば、少し見つけやすいかもしれません。

実際にそこに到達し、MySQLが「消滅」するのを防ぐには、接続プールを長く開いたままにして、古い接続をチェックアウトするという接続プールの問題を解決する必要があります。

新しい接続を取得するには、pool_recycleオプションのcreate_engine呼び出し。これを設定pool_recycleは、既存の接続を返す代わりに、新しい接続を作成するチェックアウト間の接続プール内の秒数です。

48
underrun

私は同様の問題を抱えていましたが、私にとっては、各セッションの5分から2時間の間のどこかに「MySQLがなくなった」というエラーが表示されました。

Flask-SQLAlchemyを使用しているため、アイドル状態の接続を閉じることになっていますが、接続が数時間以上アイドル状態になっていない限り、それを行っているようには見えませんでした。

最終的には、次のFlask-SQLAlchemy設定に絞り込みました。

app.config['SQLALCHEMY_POOL_SIZE'] = 100
app.config['SQLALCHEMY_POOL_RECYCLE'] = 280

これらのデフォルト設定は、それぞれ10および7200(2時間)です。

環境に合わせてこれらの設定をいじるだけです。

たとえば、SQLALCHEMY_POOL_RECYCLEを3600に設定する必要があることを多くの場所で読みましたが、それはうまくいきませんでした。私はPythonAnywhereでホストしており、5分(300秒)後にアイドル状態のMySQL接続を切断します。したがって、私の値を300未満に設定すると、問題が解決しました。

私はこの問題にあまりにも多くの時間を無駄にしたので、これが他の人の助けになることを願っています。

http://flask-sqlalchemy.pocoo.org/2.1/config/#configuration-keys

24
omerk

2018年の回答:SQLAlchemy v1.2.0 +では、この問題に対処するために利用可能な 接続プールの事前ping 機能があります「MySQLサーバーがなくなりました」。

接続プールの事前ping-接続プールには、接続チェックアウトごとにプールされた接続の「活性」をテストするオプションの「事前ping」機能が含まれ、データベースが切断された場合にDBAPI接続を透過的にリサイクルします。この機能により、「プールリサイクル」フラグが不要になり、データベースの再起動後にプールされた接続が使用されたときに発生するエラーの問題もなくなります。

新しい引数を使用すると、チェックアウト時の接続の悲観的なテストが可能です。

engine = create_engine("mysql+pymysql://user:pw@Host/db", pool_pre_ping=True)
18
wim

Flask-SQLAlchemyを使用している場合:

修正が利用できるようです: https://github.com/mitsuhiko/flask-sqlalchemy/issues/2

悲しいことに、デフォルトのインストール(pip install flask-sqlalchemy)は、特にこの問題に関して、まだパッチを適切に適用していません: https://github.com/e-dard/flask-sqlalchemy/commit/cf659f346e005d34257d256fa4c42889741fc31f

Githubから最新バージョンを入手すると修正されます。

6
Desmond Lua

このエラーが発生したとき、サイズが〜1MBのLONGBLOB/LargeBinaryイメージを保存していました。 MySQLのmax_allowed_packet構成設定を調整する必要がありました。

mysqld --max-allowed-packet=16Mを使用しました

1
Matt

プールを使用する場合、recyleをDB wait_timeoutのwait_timeoutが60未満になるように設定する必要があります。したがって、40をrecyleに設定します。

from sqlalchemy.pool import Pool
pool.QueuePool(self.get_connection, max_overflow=0,pool_size=40,recycle=50)
0
alones