Flask-sqlalchemy 在重新启动数据库服务器后失去连接

Flask-sqlalchemy losing connection after restarting of DB server

我在我的应用程序中使用了 flask-sqlalchemy。数据库是 postgresql 9.3。 我有简单的数据库初始化、模型和视图:

from config import *
from flask import Flask, request, render_template
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://%s:%s@%s/%s' % (DB_USER, DB_PASSWORD, HOST, DB_NAME)
db = SQLAlchemy(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    login = db.Column(db.String(255), unique=True, index=True, nullable=False)

db.create_all()
db.session.commit()

@app.route('/users/')
def users():
    users = User.query.all()
    return '1'

一切正常。但是当数据库服务器重新启动时(sudo service postgresql restart),在第一次请求 /users/ 时我得到 sqlalchemy.exc.OperationalError:

OperationalError: (psycopg2.OperationalError) terminating connection due to administrator command
SSL connection has been closed unexpectedly
 [SQL: ....

有没有办法在视图中更新连接,或者以其他方式设置 flask-sqlalchemy 以自动更新连接?

更新。

我最终使用清晰的 SQLAlchemy,为每个视图声明引擎、元数据和 db_session,我非常需要它。

这不是问题的解决方案,只是一个'hack'。

所以问题是开放的。我敢肯定,找到解决方案会很好 :)

SQLAlchemy documentation 解释默认行为是乐观地处理断开连接。您是否尝试了另一个请求 - 连接应该有 re-established 本身?我刚刚用 Flask/Postgres/Windows 项目对此进行了测试并且它有效。

在使用 ORM 会话的典型 Web 应用程序中,上述情况对应于单个请求因 500 错误而失败,然后 Web 应用程序继续正常运行。因此,该方法是“乐观的”,因为预计不会频繁重启数据库。

如果您希望在连接尝试之前检查连接状态,您需要编写悲观地处理断开连接的代码。文档中提供了以下示例代码:

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()

以下是 PyCharm 的调试器捕获的事件的一些屏幕截图:

Windows 7(Postgres 9.4、Flask 0.10.1、SQLAlchemy 1.0.11、Flask-SQLAlchemy 2.1 和 psycopg 2.6.1)

第一次数据库请求时 数据库重启后

Ubuntu 14.04(Postgres 9.4、Flask 0.10.1、SQLAlchemy 1.0.8、Flask-SQLAlchemy 2.0 和 psycopg 2.5.5)

第一次数据库请求时 数据库重启后

在简单的 SQLAlchemy 中,您可以在调用 create_engine 函数时添加 pool_pre_ping=True kwarg 来解决此问题。

当使用 Flask-SQLAlchemy 时,您可以使用相同的参数,但您需要在 engine_options kwarg:

中将其作为字典传递
app.db = SQLAlchemy(app, engine_options={"pool_pre_ping": True})