python - 如何教 SQLAlchemy 从断开连接中恢复?

标签 python sqlalchemy psycopg2

根据 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.

由于终端上打印了“ping server”,因此可以安全地得出事件监听器已附加的结论。如何教 SQLAlchemy 从断开连接中恢复?

最佳答案

它看起来像 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方法,并在那时采取一些措施来替换您的连接。

关于python - 如何教 SQLAlchemy 从断开连接中恢复?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28220674/

相关文章:

python - 如何使用 XlsxWriter 自动定义 excel 工作表名称?

python - Pygame 错误帮助 - pygame.error : video system not initialized

python - sqlalchemy 没有指定的驱动程序,但是指定了驱动程序

postgresql - Psycopg2 插入未保存

python - 无法在 macOS Monterey 12.3 上安装 psycopg2-binary

python - 如何检查 psycopg2 连接上的未结交易?

python - 如何在 MongoDb 中创建人类可读的 ID

sqlalchemy - 将 FK QuerySelectField 添加到 model_form() 生成的 WTForm

python - 如何处理 sqlalchemy+psycopg2 中不断变化的密码?

python - 如何将 fixture 作为参数传递给另一个 fixture