Discord Bot连接MySQL遇2006错误及PendingRollbackError的解决咨询
MySQL连接断开与事务回滚问题解决建议
核心问题分析
"MySQL server has gone away"是因为MySQL会主动断开长时间空闲的连接(默认8小时),Bot复用了失效连接;添加session.rollback()后出现的PendingRollbackError是因为事务状态异常,未正确处理会话生命周期。
具体解决方案
1. 配置SQLAlchemy连接池,自动回收失效连接
在创建引擎时添加pool_recycle和pool_pre_ping参数,提前回收连接并校验有效性:
from sqlalchemy import create_engine # 替换为你的数据库连接信息 engine = create_engine( "mysql+pymysql://username:password@host/database", pool_recycle=3600, # 1小时后自动回收连接,需小于MySQL的wait_timeout(默认28800秒) pool_pre_ping=True # 使用连接前自动检查有效性,失效则重建 )
2. 正确处理会话与事务异常
不要随意全局添加rollback(),而是在异常捕获中针对性处理,并及时销毁失效会话:
from sqlalchemy.exc import OperationalError, PendingRollbackError from your_module import Warning, create_session # 替换为你的模型和会话创建函数 def fetch_user_warnings(uid): session = create_session() try: warning = session.query(Warning).filter_by(uid=uid).limit(1).first() session.commit() return warning except OperationalError: # 连接失效,回滚事务并关闭会话,重新创建会话重试 session.rollback() session.close() session = create_session() warning = session.query(Warning).filter_by(uid=uid).limit(1).first() session.commit() return warning except PendingRollbackError: # 事务状态异常,强制回滚后重建会话 session.rollback() session.close() session = create_session() warning = session.query(Warning).filter_by(uid=uid).limit(1).first() session.commit() return warning finally: # 无论成功失败,确保会话关闭 session.close()
3. 优化会话使用习惯
- 不在Bot全局作用域创建会话对象,每个命令处理函数内单独创建和关闭会话;
- 检查MySQL配置中的
wait_timeout和interactive_timeout,确保pool_recycle的值小于这两个参数的最小值; - 避免长时间保持开启的会话,数据库操作完成后立即提交/回滚并关闭会话。
内容的提问来源于stack exchange,提问作者Ricoz
相关产品推荐
相关产品推荐

