上下文:我正在使用在CherryPy上运行的Flask应用程序,使用SQLAlchemy ORM处理数据库。
问题:
应用程序运行正常并完成我想要的一切,但是,如果我有一个页面从数据库中取出一些数据并显示,我按住“Ctrl + R”或“F5”。也就是说,不断刷新页面,进行多次数据库请求。前几个很好,然后它就破了。 记录以下错误:
(OperationalError) (2013, 'Lost connection to MySQL server during query')
Can't reconnect until invalid transaction is rolled back (original cause:
InvalidRequestError: Can't reconnect until invalid transaction is rolled back)
This result object does not return rows. It has been closed automatically.
(ProgrammingError) (2014, "Commands out of sync; you can't run this command now")
还有另一个让我困扰的错误(但这次没有记录),它是
dictionary changed size during iteration
当我使用获取的值填充字典来迭代查询时,会发生这种情况。字典是函数的本地(dict的范围)。
更多信息:
我如何处理会话:
当您输入任何页面时,会创建一个新会话,使用该会话执行所有数据库事务,并在呈现HTML之前立即关闭会话。从技术上讲,这意味着会话的范围与HTTP请求相同。
只有在session.rollback()
表或updating
期间将异常引发到表格中时,才会执行inserting
。在任何rollback()
操作期间均无query()
。
我很确定我犯了一些愚蠢的错误,或者我没有做正确的事情。
这种无限制的刷新不是真正的场景,但不容忽视。 此外,我认为当很多用户同时使用它时行为会相似。
如何处理SQLAlchemy引擎,sessionmaker :
sql_alchemy_engine = create_engine(self.db_string, echo=False, encoding="utf8", convert_unicode=True, pool_recycle=9)
sqla_session = sessionmaker(bind=sql_alchemy_engine)
它只在ONA中完成,就像在SQLA文档中推荐的那样,并且创建了一个新会话,并在需要时返回sqla_session()
。
答案 0 :(得分:3)
如果您正在使用Flask,则应使用flask-sqlalchemy,并让Flask请求上下文管理您的会话,而不是手动处理您的引擎和会话。这就是SQLAlchemy推荐的方式:
大多数Web框架都包含用于建立与请求相关联的单个会话的基础结构,该会话在请求结束时被正确构造并拆除。这些基础设施包括Flask-SQLAlchemy等产品,与Flask Web框架结合使用,以及Zope-SQLAlchemy,与Pyramid和Zope框架结合使用。 SQLAlchemy强烈建议使用这些产品。
http://docs.sqlalchemy.org/en/rel_0_9/orm/session.html?highlight=flask
然后您只需创建引擎:
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'your db uri'
db = SQLAlchemy(app)
或者,如果你正在使用app factory:
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'your db uri'
db.init_app(app)
这样,您应该使用的基本声明模型将位于db.Model
,您应该使用的会话将位于db.session
。