根据http://docs.sqlalchemy.org/en/rel_0_9/core/pooling.html#disconnect-handling-pessimistic,如果连接池中的条目不再有效,则可以检测SQLAlchemy重新连接。我创建了以下测试用例来测试它:
import subprocess
from sqlalchemy import create_engine, event
from sqlalchemy import exc
from sqlalchemy.pool import Pool
@event.listens_for(Pool, "checkout")
def ping_connection(dbapi_connection, connection_record, connection_proxy):
cursor = dbapi_connection.cursor()
try:
print "pinging server"
cursor.execute("SELECT 1")
except:
print "raising disconnect error"
raise exc.DisconnectionError()
cursor.close()
engine = create_engine('postgresql://postgres@localhost/test')
connection = engine.connect()
subprocess.check_call(['psql', str(engine.url), '-c',
"select pg_terminate_backend(pid) from pg_stat_activity " +
"where pid <> pg_backend_pid() " +
"and datname='%s';" % engine.url.database],
stdout=subprocess.PIPE)
result = connection.execute("select 'OK'")
for row in result:
print "Success!", " ".join(row)
但是我没有恢复,而是收到了这个例外:
sqlalchemy.exc.OperationalError: (OperationalError) terminating connection due to administrator command
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
因为&#34; ping服务器&#34;打印在终端上似乎可以安全地得出结论事件监听器是附加的。如何教导SQLAlchemy从断开连接中恢复?
答案 0 :(得分:5)
当你第一次从池中获得连接时,看起来checkout方法仅 被调用(例如你的connection = engine.connect()
行)
如果您随后丢失了连接,则必须明确替换它,因此您可以抓取一个新连接,然后重试您的sql:
try:
result = connection.execute("select 'OK'")
except sqlalchemy.exc.OperationalError: # may need more exceptions here
connection = engine.connect() # grab a new connection
result = connection.execute("select 'OK'") # and retry
围绕每一个sql做一个很痛苦的事情,所以你可以使用类似的东西来包装数据库查询:
def db_execute(conn, query):
try:
result = conn.execute(query)
except sqlalchemy.exc.OperationalError: # may need more exceptions here (or trap all)
conn = engine.connect() # replace your connection
result = conn.execute(query) # and retry
return result
以下内容:
result = db_execute(connection, "select 'OK'")
现在应该成功。
另一种选择是同时监听invalidate方法,并在此时采取一些措施来替换您的连接。