我有一个很少访问的Python/Flask服务器,使用SQLAlchemy。 它每隔几天被访问一次,在第一次访问时通常会出现“MySQL服务器已断开连接”的错误。 后续的页面视图都很好,但这样的初始错误看起来不专业。
我想知道正确处理这种情况的方法 - 像“设置非常长的超时时间”这样的建议,在这种情况下可能需要4天时间,似乎不正确。 如何测试缺少数据库连接并在需要时创建一个连接?
我以前也遇到过这个问题,发现处理的方法是不要保留会话。问题在于您试图保持连接的时间太长了。相反,使用线程本地作用域的会话,就像在__init__.py
或您随处导入的实用程序包中这样:
from sqlalchemy.orm import scoped_session, sessionmaker
Session = scoped_session( sessionmaker() )
首先设置引擎和元数据,这样你就可以跳过每次连接/断开时的配置机制。之后,您可以像这样执行数据库工作:
session = Session()
someObject = session.query( someMappedClass ).get( someId )
# use session like normal ...
session.close()
如果你想保留旧对象并且不想保持会话打开,那么你可以使用上述模式,并像这样重复使用旧对象:
session = Session()
someObject = session.merge( someObject )
# more db stuff
session.close()
关键是,你想打开会话、做你要做的工作,然后关闭会话。这样可以很好地避免超时。对于.merge和.add,有许多选项可让你包括已对分离对象进行的更改或从数据库加载新数据。文档非常冗长,但一旦你知道你要找什么,就可能更容易找到。
要实现最终目标并防止MySQL“消失”,需要解决连接池保持连接时间过长并为您检出旧连接的问题。
为了获得一个新的连接,你可以在create_engine调用中设置pool_recycle选项。将这个pool_recycle设置为连接池中两次检查之间的秒数。如果您想创建一个新的连接而不是返回现有的连接。
app.config['SQLALCHEMY_POOL_SIZE'] = 100
app.config['SQLALCHEMY_POOL_RECYCLE'] = 280
http://flask-sqlalchemy.pocoo.org/2.1/config/#configuration-keys
更新:2019年10月8日
自SQLAlchemy v2.4起,配置键'SQLALCHEMY_POOL_SIZE'
和'SQLALCHEMY_POOL_RECYCLE'
已被弃用,并将在v3.0中移除。请使用'SQLALCHEMY_ENGINE_OPTIONS'
来设置相应的值。
app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {'pool_size' : 100, 'pool_recycle' : 280}
SQLALCHEMY_*
键。这样他们只需拥有 SQLALCHEMY_ENGINE_OPTIONS
并将该字典直接传递给 create_engine。 - Phistrom2018年回答:在SQLAlchemy v1.2.0+中,您可以使用连接池预测功能来解决“MySQL服务器已经离开”的问题。
连接池预测 - 连接池现在包括一个可选的“预测”功能,它将为每个连接检出测试池化连接的“活性”,在数据库断开连接的情况下透明地回收DBAPI连接。此功能消除了“池回收”标志的需求以及在数据库重新启动后使用汇编连接引发错误的问题。
使用新参数可以对连接进行悲观测试:
engine = create_engine("mysql+pymysql://user:pw@host/db", pool_pre_ping=True)
@wim所描述的悲观方法是:
pool_pre_ping=True
现在,Flask-SQLAlchemy可以使用配置变量来执行此操作-->
SQLALCHEMY_POOL_PRE_PING = True
LONGBLOB
/ LargeBinary
图像。我不得不调整MySQL中的max_allowed_packet
配置设置。mysqld --max-allowed-packet=16M
。from sqlalchemy.pool import Pool
pool.QueuePool(self.get_connection, max_overflow=0,pool_size=40,recycle=50)
wait_timeout
设置为 28,800,即 8 小时。因此,如果您禁用了 pool_recycle(默认的 SQLAlchemy 行为),每隔 8 小时您将会遇到超时问题:"请注意,特别是 MySQL 将在连接上没有检测到任何活动时自动断开连接,时间为八个小时(尽管这可以通过 MySQLDB 连接本身和服务器配置进行配置)"。 - Ryan