Dify 数据库创建迁移源码解析
实现方式
通过对源码的分析,发现在 Dify 项目中,数据库迁移管理 使用 Alembic 和 Flask-Migrate 来实现。通过这两个工具,开发者能够方便地追踪、管理和应用数据库模式的变化,从而保持数据库与应用代码的一致性。
Alembic 与 Flask-Migrate 的关系
Alembic 是一个轻量级的数据库迁移工具,专为 SQLAlchemy 设计。它通过管理数据库的版本控制,帮助开发者在应用程序升级过程中安全地应用或回滚数据库模式的变更。Flask-Migrate 则是一个基于 Alembic 的扩展库,专门为 Flask 应用提供友好的接口。
Alembic 工具直接操作数据库迁移,而 Flask-Migrate 通过封装 Alembic 的命令,提供了更简单、更直观的命令行接口,简化了数据库迁移的管理。
关键源码位置:api/migrations
主要文件
在 Dify 项目中,Alembic 和 Flask-Migrate 的核心文件包括 alembic.ini
、env.py
、script.py.mako
等,它们分别在不同的阶段承担了关键作用。
-
versions:
- 存储迁移文件
-
alembic.ini:
- 这是 Alembic 的配置文件,定义了数据库连接字符串、日志级别等配置信息。
- 作用:指导 Alembic 如何连接数据库和记录操作日志,是 Alembic 运行的基础。
-
env.py:
- 该文件定义了 Alembic 的运行环境和与 Flask 应用的交互方式,包含初始化数据库环境的逻辑。
- 作用:在数据库迁移操作(如升级或降级)执行时,
env.py
会被调用,以确保正确的数据库环境配置和操作的执行。
-
script.py.mako:
- 这是一个 Mako 模板文件,用于生成新的迁移脚本模板。
- 作用:当开发者创建新的迁移时,Alembic 会根据该模板自动生成迁移脚本,提供标准化的迁移脚本结构。
迁移命令
在 Dify 项目中,数据库迁移的命令分为 Alembic 的标准命令和通过 Flask-Migrate 封装后的命令。
-
Alembic 命令:
alembic revision --autogenerate -m "message"
:自动生成一个包含数据库结构变化的迁移脚本。-m "message"
用于为迁移脚本添加描述信息。alembic upgrade head
:将数据库升级到最新的迁移版本,即应用所有尚未应用的迁移脚本。
-
Flask-Migrate 命令:
flask db migrate -m "Initial migration."
:封装后的命令,用于生成新的迁移脚本,实际上调用了alembic revision --autogenerate
。flask db upgrade
:将数据库升级到最新的迁移版本,相当于调用alembic upgrade head
。
Dify 迁移数据库流程
-
在昨晚数据库模型设计之后
flask db init
因 dify 已做项目初始化所以无需执行
flask db migrate -m "Initial migration."
flask db upgrade
最后需要将迁移文件一同提交的 git,后续部署只需要执行
flask db upgrade
注意:在更新过程中极有可能遇到版本冲突问题)
flask db upgrade
None of PyTorch, TensorFlow >= 2.0, or Flax have been found. Models won't be available and only tokenizers, configuration and file/data utilities can be used.
sagemaker.config INFO - Not applying SDK defaults from location: C:\ProgramData\sagemaker\sagemaker\config.yaml
sagemaker.config INFO - Not applying SDK defaults from location: C:\Users\Administrator\AppData\Local\sagemaker\sagemaker\config.yaml
2024-09-10 08:30:46,395.395 WARNING [MainThread] [ext_mail.py:51] - MAIL_TYPE is not set
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
ERROR [flask_migrate] Error: Multiple head revisions are present for given argument 'head'; please specify a specific target revision, '<branchname>@head' to narrow to a specific head, or 'heads' for all heads
解决
flask db heads 找到版本id
flask db merge xxx xxx 合并
flask db upgrade 更新