【问题标题】:Flask-SQLAlchemy "MySQL server has gone away" when using HAproxy使用 HAproxy 时 Flask-SQLAlchemy “MySQL 服务器已消失”
【发布时间】:2015-03-14 09:24:15
【问题描述】:

我使用 Flask 构建了一个小型 Python REST 服务,并使用 Flask-SQLAlchemy 与 MySQL DB 进行通信。

如果我直接连接到 MySQL 服务器,一切都很好,完全没有问题。如果我使用 HAproxy(处理 HA/故障转移,尽管在这个开发环境中只有一个 DB 服务器),那么如果应用程序与 DB 的通信不够频繁,我会经常收到 MySQL server has gone away 错误。

我的 HAproxy 客户端超时设置为 50 秒,所以我认为正在发生的事情是它会切断流,但应用程序不知道并尝试使用无效连接。

在使用 HAproxy 等服务时,我应该使用什么设置?

它似乎也不会自动重新连接,但如果我手动发出请求,我会得到Can't reconnect until invalid transaction is rolled back,这很奇怪,因为它只是我正在拨打的select(),所以我不这么认为是 commit() 我错过了 - 或者我应该在每个基于 ORM 的查询之后调用 commit() 吗?

【问题讨论】:

  • 我遇到了同样的问题,即“MySQL 服务器已消失”,它通常与查询返回的结果集的大小有关。尝试执行相同的查询,但强制执行限制并选择更少的列。
  • @AndyC 这个问题有运气吗?我也一样,设置池回收并不能解决它!
  • @SJoshi 在 app.config 中设置 SQLALCHEMY_POOL_RECYCLE = 30(我的 HAproxy 超时为 50)对我有用。

标签: python mysql flask flask-sqlalchemy haproxy


【解决方案1】:

只是为了用答案整理这个问题,我会发布我(认为我)为解决这些问题所做的事情。

问题 1:HAproxy

  • 将 HAproxy 客户端超时值(全局或在前端定义中)增加到比 MySQL 设置的重置时间更长的值(请参阅此interesting and related SF 问题)
  • 或在 Flask 的 app.config 中设置 SQLALCHEMY_POOL_RECYCLE = 30(在我的情况下为 30 小于 HAproxy 客户端超时),这样当数据库初始化时,它会在 HAproxy 自行切断连接之前拉入这些设置并回收连接。类似于this issue on SO

问题 2:Can't reconnect until invalid transaction is rolled back

我相信我通过调整数据库在各个模块中的初始化和导入方式来解决这个问题。我现在基本上有了一个简单的模块:

  from flask.ext.sqlalchemy import SQLAlchemy
  db = SQLAlchemy()

然后在我的主要application factory 我只是:

  from common.database import db
  db.init_app(app)

此外,由于我想轻松地自动加载表结构,我在应用程序上下文中初始化了元数据绑定,我认为正是它干净地处理了我遇到的 commit() 问题/错误,因为我相信数据库会话是现在在每次请求后正确终止。

 with app.app_context():
    # Setup DB binding
    db.metadata.bind = db.engine

【讨论】:

  • 感谢您更新答案。对于遇到此问题的其他任何人,也应该检查 my.cnf 以查看 wait_timeout 是什么样的。我有一个普通的 MariaDB,它显然设置为 10 分钟而不是 8 小时。
  • @SJoshi 我用 mariadb ,也有同样的问题。谢谢你的评论。
猜你喜欢
  • 2021-02-09
  • 1970-01-01
  • 2013-04-26
  • 1970-01-01
  • 2011-09-22
  • 2013-12-31
  • 2016-06-07
  • 1970-01-01
  • 2020-04-12
相关资源
最近更新 更多