mirror of
https://github.com/open-webui/open-webui.git
synced 2025-12-14 13:25:20 +00:00
feat:补充Alembic指南
This commit is contained in:
parent
e2eb06d5da
commit
c56585f343
1 changed files with 451 additions and 0 deletions
451
docs/ALEMBIC_GUIDE.md
Normal file
451
docs/ALEMBIC_GUIDE.md
Normal file
|
|
@ -0,0 +1,451 @@
|
||||||
|
# Alembic 使用攻略 - Open WebUI
|
||||||
|
|
||||||
|
## 🚀 快速开始
|
||||||
|
|
||||||
|
### 当前项目配置
|
||||||
|
- **自动迁移**: 应用启动时自动执行 `alembic upgrade head`
|
||||||
|
- **位置**: `backend/open_webui/config.py:53-70`
|
||||||
|
- **结论**: 拉取代码后重启应用即可,无需手动执行迁移
|
||||||
|
|
||||||
|
### 工具脚本
|
||||||
|
```bash
|
||||||
|
./scripts/migrate.sh current # 查看当前版本
|
||||||
|
./scripts/migrate.sh upgrade # 手动升级
|
||||||
|
./scripts/check-status.sh # 检查数据库与代码一致性
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 开发协作流程
|
||||||
|
|
||||||
|
### 场景1: 添加新表
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 创建迁移脚本
|
||||||
|
cd backend/open_webui
|
||||||
|
python -m alembic revision -m "add_user_credits_table"
|
||||||
|
|
||||||
|
# 2. 编辑生成的文件 migrations/versions/xxxx_add_user_credits_table.py
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
def upgrade():
|
||||||
|
op.create_table(
|
||||||
|
'user_credits',
|
||||||
|
sa.Column('id', sa.String(), nullable=False),
|
||||||
|
sa.Column('user_id', sa.String(), nullable=False),
|
||||||
|
sa.Column('credits', sa.NUMERIC(20, 6), server_default='0', nullable=False),
|
||||||
|
sa.Column('created_at', sa.BigInteger(), nullable=False),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_index('idx_user_credits_user_id', 'user_credits', ['user_id'])
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
op.drop_index('idx_user_credits_user_id', 'user_credits')
|
||||||
|
op.drop_table('user_credits')
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 3. 测试迁移
|
||||||
|
source venv/bin/activate
|
||||||
|
cd open_webui
|
||||||
|
python -m alembic upgrade head # 升级
|
||||||
|
python -m alembic downgrade -1 # 降级测试
|
||||||
|
python -m alembic upgrade head # 重新升级
|
||||||
|
|
||||||
|
# 4. 验证
|
||||||
|
python -c "
|
||||||
|
from open_webui.internal.db import get_db
|
||||||
|
from sqlalchemy import inspect
|
||||||
|
with get_db() as db:
|
||||||
|
print(inspect(db.bind).get_table_names())
|
||||||
|
"
|
||||||
|
|
||||||
|
# 5. 提交
|
||||||
|
git add migrations/versions/xxxx_add_user_credits_table.py
|
||||||
|
git add open_webui/models/credits.py
|
||||||
|
git commit -m "feat: add user credits system"
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
### 场景2: 修改现有表
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 创建迁移
|
||||||
|
python -m alembic revision -m "add_email_verified_to_user"
|
||||||
|
|
||||||
|
# 2. 编辑迁移文件
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
def upgrade():
|
||||||
|
# 添加字段
|
||||||
|
op.add_column('user', sa.Column('email_verified', sa.Boolean(),
|
||||||
|
server_default='false', nullable=False))
|
||||||
|
|
||||||
|
# 添加索引
|
||||||
|
op.create_index('idx_user_email_verified', 'user', ['email_verified'])
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
op.drop_index('idx_user_email_verified', 'user')
|
||||||
|
op.drop_column('user', 'email_verified')
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 3. 测试并提交(同场景1步骤3-5)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 场景3: 数据迁移
|
||||||
|
|
||||||
|
```python
|
||||||
|
from sqlalchemy import text
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
connection = op.get_bind()
|
||||||
|
|
||||||
|
# 1. 添加新字段
|
||||||
|
op.add_column('user', sa.Column('full_name', sa.String(), nullable=True))
|
||||||
|
|
||||||
|
# 2. 迁移数据
|
||||||
|
connection.execute(text("""
|
||||||
|
UPDATE user
|
||||||
|
SET full_name = name
|
||||||
|
WHERE full_name IS NULL
|
||||||
|
"""))
|
||||||
|
|
||||||
|
# 3. 设置为NOT NULL
|
||||||
|
op.alter_column('user', 'full_name', nullable=False)
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
op.drop_column('user', 'full_name')
|
||||||
|
```
|
||||||
|
|
||||||
|
### 场景4: 多人协作冲突
|
||||||
|
|
||||||
|
**问题**: 两个分支同时创建迁移,产生多个head
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 发现问题
|
||||||
|
python -m alembic heads
|
||||||
|
# 输出: abc123 (head), def456 (head) ← 两个头部
|
||||||
|
|
||||||
|
# 2. 合并迁移
|
||||||
|
python -m alembic merge -m "merge_feature_branches" heads
|
||||||
|
|
||||||
|
# 3. 编辑生成的合并迁移
|
||||||
|
# migrations/versions/xxx_merge_feature_branches.py
|
||||||
|
# down_revision = ('abc123', 'def456') # 已自动填充
|
||||||
|
|
||||||
|
# 4. 应用合并
|
||||||
|
python -m alembic upgrade head
|
||||||
|
|
||||||
|
# 5. 提交
|
||||||
|
git add migrations/versions/xxx_merge_feature_branches.py
|
||||||
|
git commit -m "chore: merge migration branches"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🏭 生产环境迁移
|
||||||
|
|
||||||
|
### 方式1: 自动迁移(推荐)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Docker 环境
|
||||||
|
git pull
|
||||||
|
docker-compose restart
|
||||||
|
# ✅ 应用启动时自动执行迁移
|
||||||
|
|
||||||
|
# Systemd 环境
|
||||||
|
git pull
|
||||||
|
systemctl restart open-webui
|
||||||
|
# ✅ 应用启动时自动执行迁移
|
||||||
|
|
||||||
|
# 验证
|
||||||
|
./scripts/check-status.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
**优点**: 零停机、自动化、幂等性
|
||||||
|
**适用**: 小型迁移、添加字段、创建索引
|
||||||
|
|
||||||
|
### 方式2: 手动迁移(安全)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 备份数据库(PostgreSQL)
|
||||||
|
pg_dump -U user -d openwebui_prod > backup_$(date +%Y%m%d_%H%M%S).sql
|
||||||
|
|
||||||
|
# 2. 记录当前版本
|
||||||
|
cd backend/open_webui
|
||||||
|
python -m alembic current > migration_before.txt
|
||||||
|
|
||||||
|
# 3. 拉取代码
|
||||||
|
git pull
|
||||||
|
|
||||||
|
# 4. 查看待执行的迁移
|
||||||
|
python -m alembic history | grep -A5 "$(cat migration_before.txt | awk '{print $1}')"
|
||||||
|
|
||||||
|
# 5. 手动执行迁移
|
||||||
|
python -m alembic upgrade head
|
||||||
|
|
||||||
|
# 6. 验证
|
||||||
|
python -m alembic current > migration_after.txt
|
||||||
|
diff migration_before.txt migration_after.txt
|
||||||
|
|
||||||
|
# 7. 重启应用
|
||||||
|
systemctl restart open-webui
|
||||||
|
|
||||||
|
# 8. 功能验证
|
||||||
|
curl http://localhost:8080/health
|
||||||
|
```
|
||||||
|
|
||||||
|
**优点**: 可控、可验证、可回滚
|
||||||
|
**适用**: 大型迁移、数据迁移、高风险变更
|
||||||
|
|
||||||
|
### 方式3: 蓝绿部署(零停机)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 部署新版本到绿环境(不启动)
|
||||||
|
git clone /app/open-webui /app/open-webui-green
|
||||||
|
cd /app/open-webui-green
|
||||||
|
git pull
|
||||||
|
|
||||||
|
# 2. 在绿环境执行迁移
|
||||||
|
cd backend/open_webui
|
||||||
|
python -m alembic upgrade head
|
||||||
|
|
||||||
|
# 3. 启动绿环境(连接同一数据库)
|
||||||
|
systemctl start open-webui-green
|
||||||
|
|
||||||
|
# 4. 切换流量(Nginx/负载均衡)
|
||||||
|
# 从 localhost:8080 → localhost:8081
|
||||||
|
|
||||||
|
# 5. 停止蓝环境
|
||||||
|
systemctl stop open-webui
|
||||||
|
|
||||||
|
# 6. 验证后删除蓝环境
|
||||||
|
rm -rf /app/open-webui
|
||||||
|
mv /app/open-webui-green /app/open-webui
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 常用命令速查
|
||||||
|
|
||||||
|
### 查看状态
|
||||||
|
```bash
|
||||||
|
python -m alembic current # 当前版本
|
||||||
|
python -m alembic heads # 最新版本
|
||||||
|
python -m alembic history # 历史记录
|
||||||
|
python -m alembic branches # 分支情况
|
||||||
|
```
|
||||||
|
|
||||||
|
### 执行迁移
|
||||||
|
```bash
|
||||||
|
python -m alembic upgrade head # 升级到最新
|
||||||
|
python -m alembic upgrade +1 # 升级1个版本
|
||||||
|
python -m alembic upgrade abc123 # 升级到指定版本
|
||||||
|
python -m alembic downgrade -1 # 降级1个版本
|
||||||
|
python -m alembic downgrade abc123 # 降级到指定版本
|
||||||
|
```
|
||||||
|
|
||||||
|
### 创建迁移
|
||||||
|
```bash
|
||||||
|
python -m alembic revision -m "description" # 创建空迁移
|
||||||
|
python -m alembic merge -m "merge branches" heads # 合并分支
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ 注意事项
|
||||||
|
|
||||||
|
### 1. 禁止使用 autogenerate
|
||||||
|
```bash
|
||||||
|
# ❌ 不要用(循环依赖问题)
|
||||||
|
python -m alembic revision --autogenerate -m "auto"
|
||||||
|
|
||||||
|
# ✅ 手动编写
|
||||||
|
python -m alembic revision -m "add_feature"
|
||||||
|
# 然后手动编写 upgrade/downgrade 函数
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 数据库类型(PostgreSQL)
|
||||||
|
|
||||||
|
```python
|
||||||
|
# 使用 PostgreSQL 特定类型
|
||||||
|
from sqlalchemy.dialects import postgresql
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.add_column('user',
|
||||||
|
sa.Column('balance', postgresql.NUMERIC(20, 6),
|
||||||
|
server_default='0', nullable=False))
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 大表索引创建
|
||||||
|
|
||||||
|
```python
|
||||||
|
# PostgreSQL - 在线创建索引
|
||||||
|
op.create_index(
|
||||||
|
'idx_large_table_field',
|
||||||
|
'large_table',
|
||||||
|
['field'],
|
||||||
|
postgresql_concurrently=True # 不锁表
|
||||||
|
)
|
||||||
|
|
||||||
|
# 注意: CONCURRENTLY 需要在事务外执行
|
||||||
|
# 在迁移文件顶部添加:
|
||||||
|
# revision = 'xxx'
|
||||||
|
# down_revision = 'yyy'
|
||||||
|
# branch_labels = None
|
||||||
|
# depends_on = None
|
||||||
|
#
|
||||||
|
# # 禁用事务
|
||||||
|
# def upgrade():
|
||||||
|
# op.execute('COMMIT')
|
||||||
|
# ...
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 必须编写 downgrade
|
||||||
|
|
||||||
|
```python
|
||||||
|
# ❌ 错误
|
||||||
|
def downgrade():
|
||||||
|
pass
|
||||||
|
|
||||||
|
# ✅ 正确
|
||||||
|
def downgrade():
|
||||||
|
op.drop_index('idx_user_balance')
|
||||||
|
op.drop_column('user', 'balance')
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚨 故障处理
|
||||||
|
|
||||||
|
### 迁移失败恢复
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 查看当前状态
|
||||||
|
python -m alembic current
|
||||||
|
|
||||||
|
# 2. 检查数据库是否处于中间状态
|
||||||
|
psql -U user -d dbname
|
||||||
|
\dt # 查看表
|
||||||
|
# 手动删除失败迁移创建的表/字段
|
||||||
|
|
||||||
|
# 3. 标记为指定版本(谨慎使用)
|
||||||
|
python -m alembic stamp <version_id>
|
||||||
|
|
||||||
|
# 4. 重新执行
|
||||||
|
python -m alembic upgrade head
|
||||||
|
```
|
||||||
|
|
||||||
|
### 回滚到指定版本
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 查看历史
|
||||||
|
python -m alembic history
|
||||||
|
|
||||||
|
# 2. 回滚
|
||||||
|
python -m alembic downgrade <version_id>
|
||||||
|
|
||||||
|
# 3. 重启应用
|
||||||
|
systemctl restart open-webui
|
||||||
|
```
|
||||||
|
|
||||||
|
### 强制重新初始化(危险)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# ⚠️ 会丢失所有数据
|
||||||
|
# 1. 删除 alembic_version 表
|
||||||
|
psql -U user -d dbname -c "DROP TABLE alembic_version;"
|
||||||
|
|
||||||
|
# 2. 删除所有业务表
|
||||||
|
psql -U user -d dbname -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
|
||||||
|
|
||||||
|
# 3. 重新执行所有迁移
|
||||||
|
python -m alembic upgrade head
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ 最佳实践检查清单
|
||||||
|
|
||||||
|
### 开发阶段
|
||||||
|
- [ ] 修改模型后立即创建迁移脚本
|
||||||
|
- [ ] 迁移脚本命名清晰(描述变更内容)
|
||||||
|
- [ ] 编写完整的 upgrade 和 downgrade 函数
|
||||||
|
- [ ] 使用 PostgreSQL 特定类型(NUMERIC, JSONB 等)
|
||||||
|
- [ ] 测试升级和降级流程
|
||||||
|
- [ ] Code Review 检查迁移逻辑
|
||||||
|
- [ ] 提交迁移脚本到 Git
|
||||||
|
|
||||||
|
### 部署阶段
|
||||||
|
- [ ] 备份生产数据库
|
||||||
|
- [ ] 记录当前迁移版本
|
||||||
|
- [ ] 查看待执行的迁移内容
|
||||||
|
- [ ] 评估迁移风险(大表、数据迁移)
|
||||||
|
- [ ] 选择合适的迁移方式(自动/手动)
|
||||||
|
- [ ] 执行迁移
|
||||||
|
- [ ] 验证迁移版本
|
||||||
|
- [ ] 重启应用
|
||||||
|
- [ ] 功能验证
|
||||||
|
- [ ] 监控应用日志
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 迁移决策树
|
||||||
|
|
||||||
|
```
|
||||||
|
新功能需要数据库变更
|
||||||
|
↓
|
||||||
|
修改 models/*.py
|
||||||
|
↓
|
||||||
|
创建迁移脚本 (alembic revision -m "xxx")
|
||||||
|
↓
|
||||||
|
编写 upgrade/downgrade 函数
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────┐
|
||||||
|
│ 影响是否 > 1000万行数据? │
|
||||||
|
└─────────┬───────────────────┘
|
||||||
|
│
|
||||||
|
┌─────┴─────┐
|
||||||
|
NO YES
|
||||||
|
│ │
|
||||||
|
│ 使用分批迁移/在线DDL
|
||||||
|
↓ ↓
|
||||||
|
测试升降级 准备回滚方案
|
||||||
|
│ │
|
||||||
|
└─────┬─────┘
|
||||||
|
↓
|
||||||
|
提交代码 (git commit)
|
||||||
|
↓
|
||||||
|
┌───────────┐
|
||||||
|
│ 生产部署 │
|
||||||
|
└─────┬─────┘
|
||||||
|
│
|
||||||
|
┌─────┴─────┐
|
||||||
|
风险评估
|
||||||
|
│
|
||||||
|
┌───┴───┐
|
||||||
|
低 高
|
||||||
|
│ │
|
||||||
|
│ 手动迁移
|
||||||
|
│ + 备份
|
||||||
|
自动 + 蓝绿
|
||||||
|
迁移
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 参考资源
|
||||||
|
|
||||||
|
- **项目文档**: `docs/DATABASE_CONSISTENCY_GUIDE.md` - 完整指南
|
||||||
|
- **迁移工具**: `scripts/migrate.sh` - 便捷脚本
|
||||||
|
- **状态检查**: `scripts/check-status.sh` - 一致性验证
|
||||||
|
- **Alembic 官方文档**: https://alembic.sqlalchemy.org/
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**版本**: v1.0
|
||||||
|
**更新**: 2025-12-06
|
||||||
|
**适用**: Open WebUI Next
|
||||||
Loading…
Reference in a new issue