アップデート3/4:
私はいくつかのテストを行い、チェックアウトイベントハンドラーを使用して切断をチェックすることがElixirで機能することを証明しました。私の問題はサブプロセスからの呼び出しと関係があると考え始めました更新:サブプロセスを呼び出して自分自身を反証session.commit()
か?session.commit()
しました。以下の例を更新しました。マルチプロセッシングモジュールを使用してサブプロセスを作成しています。
これがどのように機能するかを示すコードです(pool_recycle
!を使用しなくても):
from sqlalchemy import exc
from sqlalchemy import event
from sqlalchemy.pool import Pool
from elixir import *
import multiprocessing as mp
class SubProcess(mp.Process):
def run(self):
a3 = TestModel(name="monkey")
session.commit()
class TestModel(Entity):
name = Field(String(255))
@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()
from sqlalchemy import create_engine
metadata.bind = create_engine("mysql://foo:bar@localhost/some_db", echo_pool=True)
setup_all(True)
subP = SubProcess()
a1 = TestModel(name='foo')
session.commit()
# pool size is now three.
print "Restart the server"
raw_input()
subP.start()
#a2 = TestModel(name='bar')
#session.commit()
アップデート2:
MySQLのポスト1.2.2バージョンとして別の解決策を見つけることを余儀なくされています-pythonは再接続パラメータのサポートを削除します。誰かが解決策を手に入れましたか?:\
アップデート1(古いソリューション、MySQL-pythonバージョン> 1.2.2では機能しません):
解決策を見つけました:呼び出しに渡すconnect_args={'reconnect':True}
とcreate_engine
問題が修正され、自動的に再接続されます。チェックアウトイベントハンドラーも必要ないようです。
したがって、質問の例では、次のようになります。
metadata.bind = create_engine("mysql://foo:bar@localhost/db_name", pool_size=100, pool_recycle=3600, connect_args={'reconnect':True})
元の質問:
この問題に対してかなりのグーグルを実行しましたが、Elixirに固有の解決策が見つからなかったようです-SQLAlchemyドキュメントの「切断処理-悲観的」の例を使用してMySQL切断を処理しようとしています。ただし、これをテストすると(MySQLサーバーを再起動して)、チェックアウトイベントハンドラーの前に「MySQLサーバーがなくなりました」というエラーが発生します。
elixirを初期化するために使用するコードは次のとおりです。
##### Initialize elixir/SQLAlchemy
# Disconnect handling
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):
logging.debug("***********ping_connection**************")
cursor = dbapi_connection.cursor()
try:
cursor.execute("SELECT 1")
except:
logging.debug("######## DISCONNECTION ERROR #########")
# 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()
metadata.bind= create_engine("mysql://foo:bar@localhost/db_name", pool_size=100, pool_recycle=3600)
setup_all()
elixirエンティティオブジェクトを作成して保存するとsession.commit()
、上記で定義したイベントから生成された「ping_connection」メッセージが表示されます。ただし、mysqlサーバーを再起動して再度テストすると、ping接続イベントの直前にmysqlサーバーが消えたというメッセージが表示されて失敗します。
関連する行から始まるスタックトレースは次のとおりです。
File "/usr/local/lib/python2.6/dist-packages/elixir/entity.py", line 1135, in get_by
return cls.query.filter_by(*args, **kwargs).first()
File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/orm/query.py", line 1963, in first
ret = list(self[0:1])
File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/orm/query.py", line 1857, in __getitem__
return list(res)
File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/orm/query.py", line 2032, in __iter__
return self._execute_and_instances(context)
File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/orm/query.py", line 2047, in _execute_and_instances
result = conn.execute(querycontext.statement, self._params)
File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/engine/base.py", line 1399, in execute
params)
File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/engine/base.py", line 1532, in _execute_clauseelement
compiled_sql, distilled_params
File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/engine/base.py", line 1640, in _execute_context
context)
File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/engine/base.py", line 1633, in _execute_context
context)
File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/engine/default.py", line 330, in do_execute
cursor.execute(statement, parameters)
File "/usr/lib/pymodules/python2.6/MySQLdb/cursors.py", line 166, in execute
self.errorhandler(self, exc, value)
File "/usr/lib/pymodules/python2.6/MySQLdb/connections.py", line 35, in defaulterrorhandler
raise errorclass, errorvalue
OperationalError: (OperationalError) (2006, 'MySQL server has gone away')