首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >flask_sqlalchemy `pool_pre_ping`有时只工作

flask_sqlalchemy `pool_pre_ping`有时只工作
EN

Stack Overflow用户
提问于 2019-11-14 21:10:26
回答 2查看 6.5K关注 0票数 49

为了进行测试,我将MYSQL (RDS)参数修改如下;

wait_timeout = 40 (缺省值为28800) max_allowed_packet = 1GB (最大-确保问题不是由小数据包引起的) net_read_timeout = 10 interactive_timeout不变

然后在没有pool_pre_ping选项集的情况下测试我的应用程序(默认为False),使应用程序保持不活跃状态40秒,尝试登录,然后我得到

代码语言:javascript
运行
复制
Nov 14 20:05:20 ip-172-31-33-52 gunicorn[16962]: Traceback (most recent call last):
Nov 14 20:05:20 ip-172-31-33-52 gunicorn[16962]:   File "/var/www/api_server/venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1193, in _execute_context
Nov 14 20:05:20 ip-172-31-33-52 gunicorn[16962]:     context)
Nov 14 20:05:20 ip-172-31-33-52 gunicorn[16962]:   File "/var/www/api_server/venv/lib/python3.6/site-packages/sqlalchemy/engine/default.py", line 507, in do_execute
Nov 14 20:05:20 ip-172-31-33-52 gunicorn[16962]:     cursor.execute(statement, parameters)
Nov 14 20:05:20 ip-172-31-33-52 gunicorn[16962]:   File "/var/www/api_server/venv/lib/python3.6/site-packages/MySQLdb/cursors.py", line 206, in execute
Nov 14 20:05:20 ip-172-31-33-52 gunicorn[16962]:     res = self._query(query)
Nov 14 20:05:20 ip-172-31-33-52 gunicorn[16962]:   File "/var/www/api_server/venv/lib/python3.6/site-packages/MySQLdb/cursors.py", line 312, in _query
Nov 14 20:05:20 ip-172-31-33-52 gunicorn[16962]:     db.query(q)
Nov 14 20:05:20 ip-172-31-33-52 gunicorn[16962]:   File "/var/www/api_server/venv/lib/python3.6/site-packages/MySQLdb/connections.py", line 224, in query
Nov 14 20:05:20 ip-172-31-33-52 gunicorn[16962]:     _mysql.connection.query(self, query)
Nov 14 20:05:20 ip-172-31-33-52 gunicorn[16962]: MySQLdb._exceptions.OperationalError: (2013, 'Lost connection to MySQL server during query')

添加了这样的pool_pre_ping (使用flask_sqlalchamy版本2.4.1);

代码语言:javascript
运行
复制
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy as _BaseSQLAlchemy


class SQLAlchemy(_BaseSQLAlchemy):
    def apply_pool_defaults(self, app, options):
        super(SQLAlchemy, self).apply_pool_defaults(app, options)
        options["pool_pre_ping"] = True
#        options["pool_recycle"] = 30
#        options["pool_timeout"] = 35

db = SQLAlchemy()


class DevConfig():
    SQLALCHEMY_ENGINE_OPTIONS = {'pool_recycle': 280, 'pool_timeout': 100, 'pool_pre_ping': True} # These configs doesn't get applied in engine configs :/
    DEBUG = True
    # SERVER_NAME = '127.0.0.1:5000'
    SQLALCHEMY_DATABASE_URI = os.getenv('SQLALCHEMY_DATABASE_URI_DEV')
    SQLALCHEMY_TRACK_MODIFICATIONS = False

config = dict(
    dev=DevConfig,
)

app = Flask(__name__, instance_relative_config=True)
app.config.from_object(config['dev'])

# INIT DATABASE
db.init_app(app)
with app.app_context():
    db.create_all()

-----------run.py
app.run(host='127.0.0.1', port=5000)

现在,即使在MySQL服务器关闭了之前的连接之后,webapp仍然能够获得新的连接。当我在数据库被服务器关闭后访问数据库时,它总是工作得很好(试了50秒后).但是,当我长时间保持连接不活动(没有注意到,但~ >10-15分钟)时,我再次看到同样的错误。

根据文档(特别是处理断开部分),pool_pre_ping选项应该在后台仪式上处理这种场景?或者,在MySQL服务器中是否还有其他需要更改的超时变量?

EN

回答 2

Stack Overflow用户

发布于 2021-10-11 13:16:16

我设置了以下设置:

代码语言:javascript
运行
复制
SQLALCHEMY_ENGINE_OPTIONS = {
    'pool_size': 10,
    'pool_recycle': 60,
    'pool_pre_ping': True
}

过去的几个月已经停止了.

票数 2
EN

Stack Overflow用户

发布于 2021-07-28 22:32:34

来自Flask-SQLAlchemy

配置文档

某些数据库后端可能会施加不同的非活动连接超时,这会干扰的连接池。 默认情况下,MariaDB被配置为有600秒超时。这通常是很难调试的,生产环境只有一些异常,如 2013: Lost connection to MySQL server during query.如果使用的是后端(或预先配置的数据库作为服务),并且连接超时较低,则建议将SQLALCHEMY_POOL_RECYCLE设置为小于后端超时的值。

问题中引用的脚本显示了它的MySQL之间的差异

超时差(wait_timeoutnet_read_timeout)及其SQLAlchemy

(pool_recyclepool_timeout)和水瓶-SQLAlchemy

超时(SQLALCHEMY_POOL_RECYCLESQLALCHEMY_POOL_TIMEOUT)。

我们可以通过使用DevConfig助手类来协调整个应用程序中的db连接配置常量来解决这个问题。为此,我们将配置分配给静态属性并引用它们,这样就不会出现冲突的超时期望。以下是一个实现:

代码语言:javascript
运行
复制
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy as _BaseSQLAlchemy

# Coordinate DevConfig with SQLAlchemy and Flask-SQLAlchemy (don't repeat yourself!)

class DevConfig():
    SQLALCHEMY_POOL_RECYCLE = 35  # value less than backend’s timeout
    SQLALCHEMY_POOL_TIMEOUT = 7  # value less than backend’s timeout
    SQLALCHEMY_PRE_PING = True
    SQLALCHEMY_ENGINE_OPTIONS = {'pool_recycle': SQLALCHEMY_POOL_RECYCLE, 'pool_timeout': SQLALCHEMY_POOL_TIMEOUT, 'pool_pre_ping': SQLALCHEMY_PRE_PING}
    DEBUG = True
    # SERVER_NAME = '127.0.0.1:5000'
    SQLALCHEMY_DATABASE_URI = os.getenv('SQLALCHEMY_DATABASE_URI_DEV')
    SQLALCHEMY_TRACK_MODIFICATIONS = False

class SQLAlchemy(_BaseSQLAlchemy):
    def apply_pool_defaults(self, app, options):
        super(SQLAlchemy, self).apply_pool_defaults(app, options)
        options["pool_pre_ping"] = DevConfig.SQLALCHEMY_PRE_PING
#        options["pool_recycle"] = 30
#        options["pool_timeout"] = 35

db = SQLAlchemy()

config = dict(
    dev=DevConfig,
)

app = Flask(__name__, instance_relative_config=True)
app.config.from_object(config['dev'])

# INIT DATABASE
db.init_app(app)
with app.app_context():
    db.create_all()

如果您愿意,可以检查差异以查看我所做的更改:电子邮件:q1e85hc

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58866560

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档