【问题标题】:SqlAlchemy / PyMysql connection timeout on SSCursorSSCursor 上的 SqlAlchemy / PyMysql 连接超时
【发布时间】:2020-05-13 00:06:34
【问题描述】:

我正在使用 sqlalchemy 连接 mysql 数据库。我的代码看起来像

engine = sqlalchemy.create_engine(sqlalchemy.engine.url.URL(**url), connect_args={'cursorclass': SSCursor})
conn = engine.connect()

由于需要一次从DB中获取大量数据,所以我使用了SSCursor。我做了一些调查,并创建了一个 60 秒后连接丢失的场景。它是通过简单的代码模拟的,我添加了 timeout(60)。我得到如下回溯:

Exception during reset or similar
Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/pool.py", line 687, in _finalize_fairy
    fairy._reset(pool)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/pool.py", line 829, in _reset
    pool._dialect.do_rollback(self)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/dialects/mysql/base.py", line 1598, in do_rollback
    dbapi_connection.rollback()
  File "/usr/local/lib/python3.5/dist-packages/pymysql/connections.py", line 788, in rollback
    self._execute_command(COMMAND.COM_QUERY, "ROLLBACK")
  File "/usr/local/lib/python3.5/dist-packages/pymysql/connections.py", line 1067, in _execute_command
    raise err.InterfaceError("(0, '')")
pymysql.err.InterfaceError: (0, '')
Exception ignored in: <bound method MySQLResult.__del__ of <pymysql.connections.MySQLResult object at 0x7fed3af0d828>>
Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/pymysql/connections.py", line 1332, in __del__
  File "/usr/local/lib/python3.5/dist-packages/pymysql/connections.py", line 1434, in _finish_unbuffered_query
  File "/usr/local/lib/python3.5/dist-packages/pymysql/connections.py", line 983, in _read_packet
  File "/usr/local/lib/python3.5/dist-packages/pymysql/connections.py", line 1014, in _read_bytes
AttributeError: 'NoneType' object has no attribute 'settimeout'

我无法弄清楚,如何确保连接在不同的所需时间后超时。我尝试在connect_args 中使用connect_timeout,但行为没有改变。

我应该怎么做才能确保连接?

谢谢

【问题讨论】:

    标签: python sqlalchemy pymysql


    【解决方案1】:

    您应该更改 MySQL 服务器选项, 增加net_read_timeoutmax_allowed_packet的值

    https://dev.mysql.com/doc/refman/5.5/en/error-lost-connection.html

    【讨论】:

    • @cezar:包含在帖子中,“增加net_read_timeoutmax_allowed_packet的价值”这句话绝对是链接的一个有价值的部分。如果您发现它错了,您可能会否决答案。请参阅该元帖子 - meta.stackexchange.com/questions/225370/… - 关于 NAA(非答案)是什么,什么不是。
    • @Tsyvarev 您引用的部分当然很有价值,但仍然不足。 net_read_timeout 的默认值是多少?应该增加多少?答案应包含此信息,而不是依赖链接。
    • @cezar:这是低质量答案和 NAA 之间的界限。但这是一个答案。如果您觉得它提供的信息不足(我同意您的观点——“增加net_read_timeout 的价值”太含糊了),您可以将相应的评论发送给回答者,或者干脆downvote帖子...或者两者都做(打算在修复帖子后撤回反对票)。只是不要标记它。
    • @Tsyvarev 我尽量避免投反对票,因为我认为这会使人失去动力。标记应该鼓励答案改进。但你是对的,这仍然是一个答案。
    • @cezar:“标记应该鼓励答案改进” - 但是低代表用户在被标记后唯一看到的是标记的评论,这是非常抽象的。由于纯链接答案,该抽象评论实际上是有帮助的(“请至少提供链接中的一些信息”)。但在特定情况下,评论会更具体地说明答案中遗漏的内容。
    【解决方案2】:
    Traceback (most recent call last):
      File "/usr/lib/python3.6/dist-packages/pymysql/connections.py", line 1071, in __del__
      File "/usr/lib/python3.6/dist-packages/pymysql/connections.py", line 1177, in _finish_unbuffered_query
      File "/usr/lib/python3.6/dist-packages/pymysql/connections.py", line 657, in _read_packet
      File "/usr/lib/python3.6/dist-packages/pymysql/connections.py", line 688, in _read_bytes
    AttributeError: 'NoneType' object has no attribute 'settimeout'
    

    我昨晚在处理大量数据时遇到了同样的问题。 我知道问题的原因,它一定是内存/网络问题。因此我的解决方案是:

    1. 捕获异常
    2. 睡眠 60 秒
    3. 重试
                    try:
                       do_something()
                    except pymysql.OperationalError:
                        log.error("error %s: %d %s" % (row["id"], e.args[0], e.args[1]))
                        max_try = 10
                        try_times = 0
                        while con.open is False:
                            if try_times < max_try:
                                try_times += 1
                                time.sleep(60)
                                con.ping()
                        # retry
                        do_something() 
    

    如果你有钱,增加记忆力会有所帮助。如果你有时间,多多学习mysql,一遍遍地翻内存和网络。

    如果你只是想享受你的生活,那就做程序员的方式吧。这不是最好的解决方案,但我完成了我的工作。

    【讨论】:

    • 这是一个复杂的问题,不只是db server,你的app server 也需要注意。
    猜你喜欢
    • 2013-01-01
    • 2011-03-22
    • 1970-01-01
    • 2017-03-18
    • 2021-03-13
    • 2019-12-28
    • 2017-05-02
    • 2019-01-01
    • 2021-10-11
    相关资源
    最近更新 更多