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