Flask-SQLAlchemy:在回滚无效事务之前无法重新连接

时间:2015-06-29 17:30:49

标签: python mysql amazon-web-services flask flask-sqlalchemy

所以我使用Amazon Web Services RDS运行MySQL服务器并使用Python的Flask框架运行应用程序服务器,并使用Flask-SQLAlchemy与RDS进行交互。

我的应用config.py

SQLALCHEMY_DATABASE_URI = '<RDS Host>'
SQLALCHEMY_POOL_RECYCLE = 60

我的__ init __。py

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy

application = Flask(__name__)
application.config.from_object('config')
db = SQLAlchemy(application)

我有我的主要application.py

from flask import Flask
from application import db
import flask.ext.restless
from application.models import Person

application = Flask(__name__)
application.debug=True
db.init_app(application)

@application.route('/')
def index():
    return "Hello, World!"

manager = flask.ext.restless.APIManager(application, flask_sqlalchemy_db=db)
manager.create_api(Person, methods=['GET','POST', 'DELETE'])

if __name__ == '__main__':
    application.run(host='0.0.0.0')

models.py

class Person(db.Model):
    __bind_key__= 'people'
    id = db.Column(db.Integer, primary_key=True)
    firstName = db.Column(db.String(80))
    lastName = db.Column(db.String(80))
    email = db.Column(db.String(80))

    def __init__(self, firstName=None, lastName=None, email=None):
        self.firstName = firstName
        self.lastName = lastName
        self.email = email

然后我创建了一个脚本来填充数据库,以便在数据库创建和应用程序启动之后进行测试:

from application import db
from application.models import Person

person = Person('Bob', 'Jones', 'bob@website.net')
db.session.add(person)
db.session.commit()

使用db.drop_all()和db.create_all()重置数据库后,我启动application.py,然后运行脚本来填充数据库。

服务器将使用正确的JSON进行响应,但如果我几小时后回来检查它,我会收到需要回滚的错误,或者有时会发现MySQL服务器已经消失的2006错误。

人们建议我更改MySQL服务器上的超时设置但是没有修复任何东西。以下是我的设置:

innodb_lock_wait_timeout = 3000
max_allowed_packet       = 65536
net_write_timeout        = 300
wait_timeout             = 300

然后,当我查看RDS监视器时,它显示MySQL服务器保持连接打开很长一段时间,直到超时。现在纠正我,如果我错了,但是在完成之后不应该关闭连接?似乎应用程序服务器一直确保数据库连接存在,然后当MySQL服务器超时时,Flask / Flask-SQLAlchemy会抛出错误并使用它关闭应用程序服务器。

感谢任何建议,谢谢!

6 个答案:

答案 0 :(得分:9)

我认为这是添加什么

db.init_app(application)
在application.py中的

,自那以后没有出现错误。

答案 1 :(得分:3)

每次检查回滚与否都很麻烦..

我做了insert,更新需要提交的函数。

@app.teardown_request
def session_clear(exception=None):
    Session.remove()
    if exception and Session.is_active:
        Session.rollback()

答案 2 :(得分:1)

乍一看似乎事务不存在问题,但这可能是由于事先发生了Connection reset by peer之类的MySQL错误引起的。这意味着您的连接丢失,可能是因为您的应用程序上下文未正确设置。

通常,最好使用factory pattern创建您的应用。这有很多优点,您的代码是

  • 易于阅读和设置
  • 更容易测试
  • 避免循环进口

为防止无效的事务错误(可能是由OperationalError: Connection reset by peer引起的),应确保您正在处理数据库连接权限。

以下示例基于this article,该示例很好地说明了flask应用程序上下文以及如何将其与数据库连接或任何其他扩展一起使用。

application.py


from flask import Flask
from flask_sqlalchemy import SQLAlchemy

def create_app():
    """Construct the core application."""
    application = Flask(__name__)
    application.config.from_object('config')    # Set globals
    db = SQLAlchemy()

    with application.app_context():
        # Initialize globals/extensions in app context
        db.init_app(app)        

        # import routes here
        from . import routes

    return application


if __name__ == "__main__":
   app = create_app()
   app.run(host="0.0.0.0")

routes.py

from flask import current_app as application

@application.route('/', methods=['GET'])
def index():
   return "Hello, World!"

如果仍然遇到断开连接问题,还应该查看dealing with disconnects上的SQLAlchemy文档,并查看this question

答案 3 :(得分:0)

在这里,由于MySql在一段时间后关闭会话后,您缺少池回收,因此您需要添加池回收,以便池回收后池中的连接重新连接。

app.config['SQLALCHEMY_POOL_RECYCLE'] = 3600 我希望这有帮助 谢谢

答案 4 :(得分:0)

当您以单例方式创建sqlalchemy引擎时,通常会出现此错误。在这种情况下,连接失效后(以我的情况为3600秒),您会收到InvalidTransaction错误。

最好的建议是在应用程序初始化时初始化db会话

db.init_app(app)

并在需要执行任何CRUD操作时导入此数据库会话。

在我的应用程序中发布此更改后,再也不会遇到这个问题。

答案 5 :(得分:-1)

或者,在填充数据库的脚本末尾使用它:

db.session.close()

这应该可以防止那些烦人的MySQL服务器已经消失了#34;错误。