运行Telegram机器人约24小时后出现'MySQL server has gone away'错误如何解决?
wait_timeout = 28800
调整后故障依旧,运行约24小时仍会抛出相同异常。 - 将`CONN_MAX_AGE`设置为`None`,无任何改善。 - 按照网友建议安装了`mysql-server-has-gone-away` Python包,运行近24小时后还是会出现相同报错。 - 尝试手动关闭旧连接的方案,代码如下: ```python from django.db import close_old_connections try: # 执行数据库操作 except django.db.utils.OperationalError: close_old_connections() # 重试执行数据库操作
调整后仍未解决问题。
解决方案
核心原因
Django的数据库连接自动回收逻辑(基于CONN_MAX_AGE)默认仅在HTTP请求生命周期结束时触发,你运行的是长期在线的自定义Django命令,不属于HTTP请求场景,没有自动触发连接回收的时机,导致连接被MySQL服务端超时关闭后,Django仍在复用失效连接。
另外你之前在my.cnf的[client]段设置wait_timeout完全不生效,该参数是MySQL服务端配置,需要写在[mysqld]段才会生效,这也是之前调整参数没用的核心原因之一。
修复步骤
- 主动触发连接回收:给python-telegram-bot加全局前置处理器,所有更新处理前先调用
close_old_connections(),Django会自动判断连接是否过期,过期则关闭重建,不会额外消耗性能,不用修改每个业务回调函数:
from telegram.ext import BaseHandler from django.db import close_old_connections class DBConnectionPreprocessor(BaseHandler): def check_update(self, update): close_old_connections() # 返回False让后续业务handler继续处理更新 return False # 注册handler时放在最前面保证优先执行 dispatcher.add_handler(DBConnectionPreprocessor())
- 调整
CONN_MAX_AGE参数:将settings.py中的CONN_MAX_AGE设置为300(5分钟),远小于MySQL默认的8小时超时阈值,确保Django主动回收连接的时机早于MySQL关闭连接的时机。 - 兜底重试逻辑:如果仍偶现报错,可以给数据库操作加简单的重试逻辑:
from django.db import close_old_connections, OperationalError def run_db_safe(func, retries=2): for _ in range(retries): try: return func() except OperationalError: close_old_connections() # 重试耗尽后抛出原始异常 return func() # 调用示例 u = run_db_safe(lambda: Telegram.objects.get(idtelegram=userid))
内容的提问来源于stack exchange,提问作者nKn
相关产品推荐
相关产品推荐

