【问题标题】:SQLAlchemy/MySQL Lost connection to MySQL server during querySQLAlchemy/MySQL 在查询期间丢失与 MySQL 服务器的连接
【发布时间】:2015-06-27 14:41:11
【问题描述】:

SQLAlchemy (0.9.8) 和 mysql-5.6.21-osx10.8-x86_64 和 MAC OS X 10.3.3 (Yosemite)

我总是断断续续:

InterfaceError: (InterfaceError) 2013: Lost connection to MySQL server during query u'SELECT..... '

我已经阅读了一些帖子,大多数情况都可以通过将其添加到 my.cnf 来解决

   max_allowed_packet = 1024M

对于我尝试做的事情来说应该足够大了。完成此操作后,我间歇性地踩它。并将这一行放在 /etc/my.cnf 中:

   log-error = "/Users/<myname>/tmp/mysql.err.log"
   log-warnings = 3

我希望得到更多细节,但我看到的只是这样的:

   [Warning] Aborted connection 444 to db: 'dbname' user: 'root' host: 'localhost' (Got an error reading communication packets)

我已经到了这样一个地步,我认为更详细的更好的日志记录可能会有所帮助,或者在此之前我可以尝试其他的东西。

谢谢。

【问题讨论】:

    标签: python mysql macos sqlalchemy


    【解决方案1】:

    您的 MySQL 连接似乎在长时间不活动后超时,我敢打赌,如果您经常使用现有设置查询数据库,则不会发生这种情况。 MySQL 和 sql 端都有一些设置可以解决这个问题:

    1. 检查您的 SQLa 引擎的 pool_recycle 值,尝试不同/更小的值,例如1800(秒)。如果您正在从文件中读取数据库设置,请将其设置为

      pool_recycle: 1800

    否则在引擎初始化时指定它,例如

    from sqlalchemy import create_engine
    e = create_engine("mysql://user:pass@localhost/db", pool_recycle=1800)
    
    1. 检查/修改您的wait_timeout MySQL 变量,请参阅https://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_wait_timeout,这是服务器在关闭非交互式连接之前等待其活动的秒数。例如

      显示全局变量,例如“wait_timeout”;

    找到适合您环境的组合。

    【讨论】:

    • 我不认为我的案件是由于超时。我在对数据库进行连续请求期间收到此错误,因此我的代码不断查询数据库。我怀疑这是由于“缓冲区”相关问题,因为我的“累积”结果集字节大小可能非常大,尽管单个请求结果集可能不一定很大。
    • 我也遇到了同样的问题,我在第 10 分钟每小时运行一次 cronjob。为此,我正在建立连接,但每隔 10 小时它就会显示 2013 年连接丢失错误,有什么建议吗?
    • 这个解决方案从来没有为我工作过。我已经设置了 pool_recycle 和 pool_pre_ping,但它从来没有解决过这个问题。
    【解决方案2】:

    根据thisthis 和互联网上许多其他文章的建议,使用以下装饰器包装我的所有函数帮助我解决了以 mariadb 作为后端数据库的“丢失连接”问题。请注意,下面的 dbflask_sqlalchemy.SQLAlchemy 的一个实例,但是对于 sqlalchemy 会话,这个概念也将保持不变。

    def manage_session(f):
        def inner(*args, **kwargs):
    
            # MANUAL PRE PING
            try:
                db.session.execute("SELECT 1;")
                db.session.commit()
            except:
                db.session.rollback()
            finally:
                db.session.close()
    
            # SESSION COMMIT, ROLLBACK, CLOSE
            try:
                res = f(*args, **kwargs)
                db.session.commit()
                return res
            except Exception as e:
                db.session.rollback()
                raise e
                # OR return traceback.format_exc()
            finally:
                db.session.close()
        return inner
    

    我还在 Flask SQLAlchemy 配置中添加了 50 秒的 pool_recycle,但这对解决方案没有明显贡献。

    编辑1:

    下面是在最终代码中如何使用它的示例 sn-p:

    from flask_restful import Resource
    
    class DataAPI(Resource):
    
        @manage_session
        def get(self):
            # Get data rows from DB
    
    

    【讨论】:

    • 你怎么称呼这个?
    • @RyanH - 添加了一个示例作为对答案的编辑。
    猜你喜欢
    • 1970-01-01
    • 2012-11-15
    • 2020-07-11
    • 2015-11-22
    • 1970-01-01
    • 1970-01-01
    • 2015-09-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多