在不常用的Python/Flask服务器上使用SQLAlchemy避免"MySQL服务器已经消失"

Oll*_*ass 50 python mysql database-connection sqlalchemy flask

Flask/SQLAlchemy如何配置为创建新的数据库连接(如果不存在)?

我有一个不经常访问的Python/Flask服务器,它使用SQLAlchemy.每隔几天就会访问一次,并且在第一次访问时它经常会抛出"MySQL服务器已经消失"的错误.后续的页面视图很好,但是出现这个初始错误看起来不合适.

我想知道处理这个问题的正确方法 - 像"长时间休息"这样的建议,在这种情况下大约需要4天,似乎不正确.如何测试缺少数据库连接并在需要时创建一个?

und*_*run 48

我以前遇到过麻烦,并发现处理它的方法是不保持会话.麻烦的是你试图保持连接打开的时间太长.相反,__init__.py在任何位置导入的实用程序包中或其中使用线程本地作用域会话:

from sqlalchemy.orm import scoped_session, sessionmaker
Session = scoped_session( sessionmaker() )
Run Code Online (Sandbox Code Playgroud)

然后设置一次引擎和元数据.这允许您在每次连接/断开连接时跳过配置机制.之后,您可以像这样执行数据库工作:

session = Session()
someObject = session.query( someMappedClass ).get( someId )
# use session like normal ...
session.close()
Run Code Online (Sandbox Code Playgroud)

如果您想要保留旧对象并且不想让会话保持打开状态,那么您可以使用上述模式并重用旧对象,如下所示:

session = Session()
someObject = session.merge( someObject )
# more db stuff
session.close()
Run Code Online (Sandbox Code Playgroud)

关键是,您要打开会话,完成工作,然后关闭会话.这样可以很好地避免超时..merge和.add有很多选项,允许您包含对分离对象所做的更改或从数据库加载新数据.文档非常详细,但一旦你知道你在寻找什么,它可能会更容易找到.

要实际完全到达并防止MySQL"离开",您需要解决连接池的问题,保持连接打开时间过长并为您检查旧连接.

要获得全新连接,您可以pool_recyclecreate_engine通话中设置选项.将此pool_recycle值设置为您希望创建新连接而不是返回现有连接的检出之间连接池中的秒数.

  • 听起来你可能需要设置一个pool_recycle时间 - 我编辑了我的答案. (2认同)
  • 为了清楚起见,您需要答案的两个元素(原始和更新)来解决此问题。 (2认同)

小智 25

我有一个类似的问题,但对我来说,我会在每个会话的5分钟到2个小时之间的某个地方得到"MySQL已经消失"的错误.

我正在使用Flask-SQLAlchemy,所以它应该关闭空闲连接,但似乎没有这样做,除非连接已经空闲了几个小时.

最后,我将其缩小到以下Flask-SQLAlchemy设置:

app.config['SQLALCHEMY_POOL_SIZE'] = 100
app.config['SQLALCHEMY_POOL_RECYCLE'] = 280
Run Code Online (Sandbox Code Playgroud)

这些的默认设置分别为10和7200(2小时).

这是设置适合您的环境的问题.

例如,我在许多地方读过SQLALCHEMY_POOL_RECYCLE应该设置为3600,但这对我不起作用.我正在使用PythonAnywhere托管,他们在5分钟(300秒)后杀死闲置的MySQL连接.因此将我的值设置为小于300可以解决问题.

我希望这有助于其他人,因为我在这个问题上浪费了太多时间.

http://flask-sqlalchemy.pocoo.org/2.1/config/#configuration-keys

  • 实际上,我们的文档中有一个关于 pool_recycle 值的页面:http://help.pythonanywhere.com/pages/UsingSQLAlchemywithMySQL (3认同)

wim*_*wim 19

2018回答: 在SQLAlchemy v1.2.0 +中,您可以使用连接池预ping功能来解决此问题"MySQL服务器已经消失".

连接池预ping - 连接池现在包括一个可选的"预ping"功能,该功能将测试每个连接检出的池连接的"活跃度",如果数据库断开连接,则透明地回收DBAPI连接.此功能消除了对"池循环"标志的需要以及在数据库重新启动后使用池连接时引发的错误问题.

使用新参数可以在结账时对连接进行悲观测试:

engine = create_engine("mysql+pymysql://user:pw@host/db", pool_pre_ping=True)
Run Code Online (Sandbox Code Playgroud)

  • 从@MasashiMiyazaki链接到SQLAlchemy的这个解决方案:https://github.com/mitsuhiko/flask-sqlalchemy/issues/589#issuecomment-361075700 (2认同)

Des*_*Lua 6

如果您使用Flask-SQLAlchemy:

似乎有一个修复程序可用:https://github.com/mitsuhiko/flask-sqlalchemy/issues/2

遗憾的是,默认安装(pip install flask-sqlalchemy)尚未正确应用补丁,尤其是在此问题上:https://github.com/e-dard/flask-sqlalchemy/commit/cf659f346e005d34257d256fa4c42889741fc31f

从github获取最新版本应该解决它.

  • 如果您不希望使用Flask-SQLAlchemy的前沿,则可以将SQLALCHEMY_POOL_RECYCLE配置值设置为7200. (2认同)

小智 6

@wim 描述的悲观方法

pool_pre_ping=真

现在可以使用配置变量为 Flask-SQLAlchemy 完成 -->

SQLALCHEMY_POOL_PRE_PING = True