
RFC: Replace Peewee with SQLModel
快速结论:该 Issue 是 RAGFlow 社区提出的 ORM 替换 RFC(Peewee → SQLModel),并非已复现的 Bug。问题背景反映了 Peewee 在连接管理、嵌套上下文冲突和丢失连接恢复上的固有缺陷,但方案仍处于 Draft / PR 阶段。如果希望参与迁移或评估影响,优先查看两个基础 PR(#14776、#14777)以及项目后续计划的 Go 版本重构进度。
问题场景
在 RAGFlow 项目 Python 后端的开发/维护过程中,团队发现基于 Peewee 的 ORM 架构在以下场景中频繁触发连接问题:批量插入时会嵌套 @DB.connection_context() 装饰器(覆盖 api/db/services/ 下约 215 处调用点);手动调用的 db.connect() / db.close() 存在于 agent_api.py 和 apps/__init__.py 中;MySQL 错误码 2013/2006 导致 InterfaceError: (0, '') 或连接泄漏。
报错原文
InterfaceError: (0, '')
Lost connection to MySQL server during query (error: 2013)
MySQL server has gone away (error: 2006)
原因分析
根本原因来自 Peewee 自身的短板,并非特定版本的 Bug:
- 嵌套连接上下文冲突:
@DB.connection_context()是“扁平”(flat) 装饰器,不能在嵌套调用中明智地跟踪引用计数,导致子层误打开或错误返回连接,触发InterfaceError。 - 手动连接管理散乱:agent_api.py 中
test_db_connection手动 open/close,apps/__init__.py 全局异常处理器中也会关闭连接,缺乏统一协议。 - Peewee 内置连接池无法可靠恢复连接:项目不得不自己实现
RetryingPooledMySQLDatabase(db_models.py:260)来捕获OperationalError, InterfaceError并重试。 - 会话生命周期不明确:没有统一的“请求-连接”管理主体,长时间任务和并发请求的连接释放难以控制。
环境排查
- ORM/依赖:Peewee(当前使用)、SQLAlchemy 2.0(迁移目标底层)、SQLModel(统一数据模型)、Alembic(数据库迁移脚手架)
- Python 版本:未在 Issue 中指定,建议参考项目 pyproject.toml
- 数据库:MySQL(错误码 2013/2006 提示连接丢失)
- 框架:FastAPI(SQLModel 作者与 FastAPI 作者相同)
解决步骤
按 Issue 讨论和 PR 进展,以下是社区规划的迁移路径:
- 审查并合入基础设施 PR:检查 PR #14776(SQLAlchemy 2.0 引擎、scoped_session、Alembic 脚手架、pyproject.toml 依赖)和 PR #14777(修复 test_db_connection 连接泄漏)。目前 Peewee 代码不被触及。
- 生成 Alembic 基线迁移:从当前数据库实时 Schema 生成第一个 Alembic 迁移文件。
- 增量转换服务层:将 api/db/services/ 下约 215 处
@DB.connection_context()逐步替换为 SQLModel / SQLAlchemy 会话管理。 - 协调冲突分支:Issuer 在评论中明确表示“Phase 3 会与大多数开放功能分支发生冲突”,建议开始前确认当前活跃开发方向。
- (注意:作者在评论末尾透露 RAGFlow 项目“nearly done porting … from python to go”,Python 端即将消亡。因此直接参与 SQLModel 迁移可能不是社区当前首要目标,建议同步评估 Go 版本进度。)
验证方法
该 Issue 是 RFC(Request for Comments),并非 Bug,没有标准验证方法。如果按 PR 步骤合并后,可通过以下方式确认环境是否正常:
- 运行现有单元测试(特别是 api/db/services/ 下的连接相关测试)
- 启动 RAGFlow 应用并模拟多层嵌套
connection_context的业务流程(如批量插入 + 子服务调用),观察是否有InterfaceError复现 - 检查 MySQL 的错误日志,确认不再出现 2013/2006 断开错误



