【问题标题】:Flask-sqlalchemy losing connection after restarting of DB server重启数据库服务器后 Flask-sqlalchemy 失去连接
【发布时间】:2016-04-22 01:16:24
【问题描述】:

我在我的应用程序中使用了 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。

这不是问题的解决方案,只是一个“黑客”。

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

【问题讨论】:

    标签: postgresql flask sqlalchemy flask-sqlalchemy psycopg2


    【解决方案1】:

    SQLAlchemy documentation 解释说默认行为是乐观地处理断开连接。您是否尝试了另一个请求 - 连接应该已经重新建立起来?我刚刚使用 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)

    在第一个数据库请求时 db 重启后

    【讨论】:

    • 不幸的是它没有帮助。重新启动数据库服务器后的第一个请求,此事件不执行。如果在视图中调用 ping_connection(params) 函数,它没有帮助。
    • @user1931780 - 有趣 - 我通过 PyCharm 的调试器(在 Windows 和 Ubuntu 上)运行了代码,并按预期处理了重启。我列出了使用的库版本。
    • 好帖子!按预期工作!非常感谢@pjcunningham!
    【解决方案2】:

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

    当使用Flask-SQLAlchemy 时,您可以使用相同的参数,但您需要在engine_options kwarg 中将其作为dict 传递:

    app.db = SQLAlchemy(app, engine_options={"pool_pre_ping": True})
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-29
      • 2015-01-12
      • 2022-07-07
      • 2017-09-15
      • 2012-05-23
      • 1970-01-01
      • 1970-01-01
      • 2021-11-02
      相关资源
      最近更新 更多