aiomysql在Discord bot事件中随机触发Task pending销毁报错如何排查?
你遇到的Task was destroyed but it is pending!错误核心原因是绑定到Discord事件的异步任务还没执行完成就被垃圾回收销毁了,结合你的代码,具体问题和修复方案如下:
问题根因
- 连接池被重复创建覆盖
discord.py的on_ready事件并非仅触发一次,每次和Discord网关重连后都会重新触发该事件。你的getpool函数没有做防重复判断,每次调用都会生成新的连接池并覆盖全局变量,旧连接池中还在被使用的连接会变成游离状态,依赖这些连接的数据库操作会直接卡住,导致对应的事件任务一直处于pending状态,最终被销毁时报错。 - 连接池配置错误
你将pool_recycle参数设为0,关闭了连接自动回收逻辑。MySQL服务端默认会主动断开空闲超过8小时的连接,aiomysql无法主动感知连接已失效,执行查询时会一直等待响应,也会导致任务卡住。 - 缺少连接池清理逻辑
bot进程退出或断开重连时,没有手动关闭现有连接池,正在执行的数据库操作会被强制中断,pending状态的任务就会触发报错。 - 缺少边界情况处理
如果bot启动后,on_ready还没执行完成就收到了事件,此时全局pool还是None,调用数据库操作方法会直接抛出未捕获异常,也可能导致任务异常终止。
修复方案
- 调整连接池初始化逻辑,避免重复创建
修改mysqlconnection.py中的getpool函数,增加初始化判断,同时调整pool_recycle配置:
async def getpool(): global pool # 仅当连接池不存在时才创建,避免重复覆盖 if pool is None: pool = await aiomysql.create_pool( host="", user="", password="", db="", pool_recycle=3600, # 配置为1小时自动回收连接,小于MySQL默认的8小时超时即可 minsize=2, # 最小空闲连接数,按需调整 maxsize=10 # 最大连接数,按需调整 )
- 增加连接池清理逻辑
在bot.py中注册断开连接钩子,进程退出或重连时主动释放连接池:
@bot.event async def on_disconnect(): global pool if pool is not None: pool.close() await pool.wait_closed() pool = None
- 给事件回调增加异常捕获
所有涉及数据库操作的事件回调外层增加异常捕获,避免未处理异常导致任务卡住:
async def on_raw_message_delete(payload): try: # 你的原有业务逻辑,包含数据库操作代码 except Exception as e: # 按需打印日志或者上报错误 print(f"on_raw_message_delete处理失败: {str(e)}")
- 可选:增加连接池初始化判断
可以在execute_search和execute_alter函数开头增加判断,如果连接池还未初始化,先等待getpool执行完成,避免启动阶段调用报错。
内容的提问来源于stack exchange,提问作者Lysander12 PT
相关产品推荐
相关产品推荐

