forked from xiaohei/taiji-AI-PAD
663 lines
18 KiB
Markdown
663 lines
18 KiB
Markdown
# 生产环境数据库同步指南
|
||
|
||
生成时间: 2026-03-12
|
||
测试环境数据库: `taiji`
|
||
生产环境数据库: `taiji_prod`
|
||
|
||
## 📋 迁移总览
|
||
|
||
测试环境在 2026年3月9-12日期间执行了 **8个数据库迁移**,需要同步到生产环境:
|
||
|
||
| 迁移编号 | 文件名 | 类型 | 影响范围 | 风险等级 |
|
||
|---------|--------|------|----------|---------|
|
||
| 017 | add_external_data_tools.sql | 新增表 | 外部数据工具功能 | 🟢 低 |
|
||
| 018 | add_external_toolkits.sql | 新增表 | 外部工具集功能 | 🟢 低 |
|
||
| 019 | add_agent_model_name.sql | 字段新增 | `agents`、`agent_billing_records` | 🟢 低 |
|
||
| 020 | fix_quota_defaults.sql | 字段修改 | 配额表(3个表) | 🟡 中 |
|
||
| 021 | fix_agent_type_length.sql | 字段修改 | `agent_billing_records` | 🟢 低 |
|
||
| 022 | fix_eu_equals_cost.sql | 字段类型+数据修正 | `agent_billing_records`、`model_billing_records` | 🟡 中 |
|
||
| 023 | fix_billing_channel_id.sql | 数据修正 | `agent_billing_records`、`model_billing_records` | 🟢 低 |
|
||
| 024 | add_record_type.sql | 字段新增+数据修正 | `agent_billing_records` | 🟡 中 |
|
||
|
||
---
|
||
|
||
## 📝 详细迁移内容
|
||
|
||
### 迁移 017: 添加外部数据工具表
|
||
|
||
**文件**: `services/mcp-server/migrations/017_add_external_data_tools.sql`
|
||
|
||
**目的**: 支持用户创建和管理自定义的外部API数据工具
|
||
|
||
**操作**:
|
||
```sql
|
||
-- 创建表
|
||
CREATE TABLE external_data_tools (
|
||
id UUID PRIMARY KEY,
|
||
name VARCHAR(100) NOT NULL,
|
||
description TEXT,
|
||
url VARCHAR(500) NOT NULL,
|
||
method VARCHAR(10) DEFAULT 'POST',
|
||
auth_type VARCHAR(20) DEFAULT 'none',
|
||
tool_ref_id VARCHAR(100) UNIQUE,
|
||
status VARCHAR(20) DEFAULT 'pending',
|
||
error_message TEXT,
|
||
owner_id UUID NOT NULL REFERENCES users(id),
|
||
tenant_id UUID REFERENCES users(id),
|
||
channel_id UUID REFERENCES channels(id),
|
||
is_active BOOLEAN DEFAULT TRUE,
|
||
usage_count INTEGER DEFAULT 0,
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||
);
|
||
|
||
-- 索引
|
||
CREATE INDEX idx_external_data_tool_owner ON external_data_tools(owner_id);
|
||
CREATE INDEX idx_external_data_tool_ref ON external_data_tools(tool_ref_id);
|
||
CREATE INDEX idx_external_data_tool_status ON external_data_tools(status);
|
||
```
|
||
|
||
**影响**: 新功能,对现有数据无影响
|
||
|
||
**回滚方案**:
|
||
```sql
|
||
DROP TABLE IF EXISTS external_data_tools CASCADE;
|
||
```
|
||
|
||
---
|
||
|
||
### 迁移 018: 添加外部数据工具集表
|
||
|
||
**文件**: `services/mcp-server/migrations/018_add_external_toolkits.sql`
|
||
|
||
**目的**: 允许用户将多个外部工具组合成工具集,方便部署自定义Agent
|
||
|
||
**操作**:
|
||
```sql
|
||
-- 创建表
|
||
CREATE TABLE external_toolkits (
|
||
id UUID PRIMARY KEY,
|
||
name VARCHAR(100) NOT NULL,
|
||
description TEXT,
|
||
tool_ids JSONB NOT NULL DEFAULT '[]'::jsonb,
|
||
owner_id UUID NOT NULL REFERENCES users(id),
|
||
tenant_id UUID REFERENCES users(id),
|
||
channel_id UUID REFERENCES channels(id),
|
||
is_active BOOLEAN DEFAULT TRUE,
|
||
usage_count INTEGER DEFAULT 0,
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
CONSTRAINT uq_toolkit_name_owner UNIQUE (name, owner_id)
|
||
);
|
||
|
||
-- 索引
|
||
CREATE INDEX idx_external_toolkit_owner ON external_toolkits(owner_id);
|
||
```
|
||
|
||
**影响**: 新功能,对现有数据无影响
|
||
|
||
**回滚方案**:
|
||
```sql
|
||
DROP TABLE IF EXISTS external_toolkits CASCADE;
|
||
```
|
||
|
||
---
|
||
|
||
### 迁移 019: 为Agent添加模型名称字段 ⭐ 重要
|
||
|
||
**文件**: `services/mcp-server/migrations/019_add_agent_model_name.sql`
|
||
|
||
**目的**:
|
||
- 记录每个Agent使用的LLM模型(如 `azure/gpt-4`, `gemini/gemini-pro`)
|
||
- 支持计费记录中追踪模型使用情况
|
||
|
||
**操作**:
|
||
```sql
|
||
-- 1. agents 表添加 model_name 字段
|
||
ALTER TABLE agents ADD COLUMN IF NOT EXISTS model_name VARCHAR(100);
|
||
CREATE INDEX IF NOT EXISTS idx_agent_model_name ON agents(model_name);
|
||
|
||
-- 2. agent_billing_records 表添加 model_name 字段
|
||
ALTER TABLE agent_billing_records ADD COLUMN IF NOT EXISTS model_name VARCHAR(100);
|
||
CREATE INDEX IF NOT EXISTS idx_agent_billing_model_name ON agent_billing_records(model_name);
|
||
```
|
||
|
||
**影响**:
|
||
- 现有Agent的 `model_name` 为 NULL(可接受)
|
||
- 新创建的Agent将记录模型信息
|
||
|
||
**注意事项**:
|
||
- ⚠️ 如果生产环境已有该字段,使用 `IF NOT EXISTS` 将安全跳过
|
||
- 该字段为 **可空**,不强制现有记录填充
|
||
|
||
**回滚方案**:
|
||
```sql
|
||
ALTER TABLE agents DROP COLUMN IF EXISTS model_name;
|
||
ALTER TABLE agent_billing_records DROP COLUMN IF EXISTS model_name;
|
||
DROP INDEX IF EXISTS idx_agent_model_name;
|
||
DROP INDEX IF EXISTS idx_agent_billing_model_name;
|
||
```
|
||
|
||
---
|
||
|
||
### 迁移 020: 修复配额字段默认值 ⚠️ 需要谨慎
|
||
|
||
**文件**: `services/mcp-server/migrations/020_fix_quota_defaults.sql`
|
||
|
||
**目的**:
|
||
- 消除配额字段的 NULL 值,避免计算错误
|
||
- 添加 NOT NULL 约束和检查约束
|
||
|
||
**操作**:
|
||
```sql
|
||
-- 1. tenant_custom_agent_quotas 表
|
||
ALTER TABLE tenant_custom_agent_quotas
|
||
ALTER COLUMN cpu_quota SET DEFAULT 0, ALTER COLUMN cpu_quota SET NOT NULL,
|
||
ALTER COLUMN memory_quota SET DEFAULT 0, ALTER COLUMN memory_quota SET NOT NULL,
|
||
ALTER COLUMN cpu_used SET DEFAULT 0, ALTER COLUMN cpu_used SET NOT NULL,
|
||
ALTER COLUMN memory_used SET DEFAULT 0, ALTER COLUMN memory_used SET NOT NULL,
|
||
ALTER COLUMN agent_count SET DEFAULT 0, ALTER COLUMN agent_count SET NOT NULL;
|
||
|
||
UPDATE tenant_custom_agent_quotas SET cpu_quota = 0 WHERE cpu_quota IS NULL;
|
||
UPDATE tenant_custom_agent_quotas SET memory_quota = 0 WHERE memory_quota IS NULL;
|
||
UPDATE tenant_custom_agent_quotas SET cpu_used = 0 WHERE cpu_used IS NULL;
|
||
UPDATE tenant_custom_agent_quotas SET memory_used = 0 WHERE memory_used IS NULL;
|
||
UPDATE tenant_custom_agent_quotas SET agent_count = 0 WHERE agent_count IS NULL;
|
||
|
||
-- 添加检查约束
|
||
ALTER TABLE tenant_custom_agent_quotas
|
||
ADD CONSTRAINT chk_tenant_cpu_used CHECK (cpu_used <= cpu_quota),
|
||
ADD CONSTRAINT chk_tenant_memory_used CHECK (memory_used <= memory_quota);
|
||
|
||
-- 2. channel_custom_agent_quotas 表(类似操作)
|
||
-- 3. platform_agent_quotas 表(类似操作)
|
||
```
|
||
|
||
**影响**:
|
||
- ⚠️ **数据修改**: 将所有 NULL 值更新为 0
|
||
- ⚠️ **约束添加**: 新增检查约束,使用量不能超过配额
|
||
|
||
**⚠️ 执行前检查**:
|
||
```sql
|
||
-- 检查生产环境是否有 NULL 值
|
||
SELECT
|
||
COUNT(*) as total_records,
|
||
COUNT(CASE WHEN cpu_quota IS NULL THEN 1 END) as null_cpu_quota,
|
||
COUNT(CASE WHEN memory_quota IS NULL THEN 1 END) as null_memory_quota
|
||
FROM tenant_custom_agent_quotas;
|
||
|
||
-- 检查是否有使用量超过配额的记录(会导致约束添加失败)
|
||
SELECT * FROM tenant_custom_agent_quotas WHERE cpu_used > cpu_quota;
|
||
SELECT * FROM tenant_custom_agent_quotas WHERE memory_used > memory_quota;
|
||
```
|
||
|
||
**回滚方案**:
|
||
```sql
|
||
-- 删除约束(如果需要)
|
||
ALTER TABLE tenant_custom_agent_quotas DROP CONSTRAINT IF EXISTS chk_tenant_cpu_used;
|
||
ALTER TABLE tenant_custom_agent_quotas DROP CONSTRAINT IF EXISTS chk_tenant_memory_used;
|
||
-- 注意:无法回滚 NOT NULL 约束和数据修改
|
||
```
|
||
|
||
---
|
||
|
||
### 迁移 021: 修复agent_type字段长度
|
||
|
||
**文件**: `services/mcp-server/migrations/021_fix_agent_type_length.sql`
|
||
|
||
**目的**: 修复 `microsoft_learn_agent`(22字符)超出 VARCHAR(20) 限制的问题
|
||
|
||
**操作**:
|
||
```sql
|
||
ALTER TABLE agent_billing_records ALTER COLUMN agent_type TYPE VARCHAR(100);
|
||
```
|
||
|
||
**影响**: 扩展字段长度,对现有数据无负面影响
|
||
|
||
**测试建议**:
|
||
```sql
|
||
-- 检查是否有被截断的数据
|
||
SELECT agent_type, LENGTH(agent_type) as len, COUNT(*)
|
||
FROM agent_billing_records
|
||
GROUP BY agent_type
|
||
ORDER BY len DESC;
|
||
```
|
||
|
||
**回滚方案**:
|
||
```sql
|
||
-- 仅在确认所有值都 ≤20 字符时才能回滚
|
||
ALTER TABLE agent_billing_records ALTER COLUMN agent_type TYPE VARCHAR(20);
|
||
```
|
||
|
||
---
|
||
|
||
### 迁移 022: 修复EU计算逻辑 ⚠️ 重要数据修正
|
||
|
||
**文件**: `services/mcp-server/migrations/022_fix_eu_equals_cost.sql`
|
||
|
||
**目的**:
|
||
- **旧逻辑**: `EU = ceil(duration_seconds / 10)`,即 1 EU = 10秒
|
||
- **新逻辑**: `EU = Cost(美元)`,即 1 EU = 1 美元
|
||
- 将历史数据的 `eu_consumed` 修正为 `cost` 的值
|
||
|
||
**操作**:
|
||
```sql
|
||
-- 1. 修改字段类型以支持小数
|
||
ALTER TABLE agent_billing_records
|
||
ALTER COLUMN eu_consumed TYPE NUMERIC(12, 4);
|
||
|
||
-- 2. 更新历史数据
|
||
UPDATE agent_billing_records
|
||
SET eu_consumed = cost
|
||
WHERE cost IS NOT NULL AND cost > 0;
|
||
|
||
UPDATE model_billing_records
|
||
SET eu_consumed = total_cost
|
||
WHERE total_cost IS NOT NULL AND total_cost > 0;
|
||
|
||
-- 3. 添加注释说明
|
||
COMMENT ON COLUMN agent_billing_records.eu_consumed IS 'EU 消耗(1 EU = 1 美元,EU = Cost)';
|
||
```
|
||
|
||
**影响**:
|
||
- ⚠️ **修改所有历史计费记录**的 `eu_consumed` 值
|
||
- 会导致历史数据的EU统计发生变化
|
||
|
||
**⚠️ 执行前备份**:
|
||
```sql
|
||
-- 备份历史数据
|
||
CREATE TABLE agent_billing_records_backup_20260312 AS
|
||
SELECT * FROM agent_billing_records;
|
||
|
||
CREATE TABLE model_billing_records_backup_20260312 AS
|
||
SELECT * FROM model_billing_records;
|
||
```
|
||
|
||
**验证**:
|
||
```sql
|
||
-- 检查 EU 和 Cost 是否一致
|
||
SELECT id, agent_name, eu_consumed, cost,
|
||
CASE WHEN ABS(eu_consumed - cost) < 0.0001 THEN 'OK' ELSE 'MISMATCH' END as status
|
||
FROM agent_billing_records
|
||
WHERE cost > 0
|
||
LIMIT 20;
|
||
```
|
||
|
||
**回滚方案**:
|
||
```sql
|
||
-- 从备份表恢复
|
||
UPDATE agent_billing_records abr
|
||
SET eu_consumed = backup.eu_consumed
|
||
FROM agent_billing_records_backup_20260312 backup
|
||
WHERE abr.id = backup.id;
|
||
```
|
||
|
||
---
|
||
|
||
### 迁移 023: 修复计费记录中缺失的channel_id
|
||
|
||
**文件**: `services/mcp-server/migrations/023_fix_billing_channel_id.sql`
|
||
|
||
**目的**: 修复计费记录创建时未正确设置 `channel_id` 的问题
|
||
|
||
**操作**:
|
||
```sql
|
||
-- 1. 更新 AgentBillingRecord
|
||
UPDATE agent_billing_records abr
|
||
SET channel_id = u.channel_id
|
||
FROM users u
|
||
WHERE abr.user_id = u.id
|
||
AND abr.channel_id IS NULL
|
||
AND u.channel_id IS NOT NULL;
|
||
|
||
-- 2. 更新 ModelBillingRecord
|
||
UPDATE model_billing_records mbr
|
||
SET channel_id = u.channel_id
|
||
FROM users u
|
||
WHERE mbr.tenant_id = u.id
|
||
AND mbr.channel_id IS NULL
|
||
AND u.channel_id IS NOT NULL;
|
||
```
|
||
|
||
**影响**: 补充缺失的 `channel_id`,提高数据完整性
|
||
|
||
**执行前检查**:
|
||
```sql
|
||
-- 检查有多少记录缺失 channel_id
|
||
SELECT
|
||
'AgentBillingRecord' as table_name,
|
||
COUNT(*) as total,
|
||
COUNT(channel_id) as with_channel,
|
||
COUNT(*) - COUNT(channel_id) as without_channel
|
||
FROM agent_billing_records
|
||
UNION ALL
|
||
SELECT
|
||
'ModelBillingRecord' as table_name,
|
||
COUNT(*) as total,
|
||
COUNT(channel_id) as with_channel,
|
||
COUNT(*) - COUNT(channel_id) as without_channel
|
||
FROM model_billing_records;
|
||
```
|
||
|
||
**回滚方案**: 无需回滚(数据修正)
|
||
|
||
---
|
||
|
||
### 迁移 024: 添加record_type字段 ⚠️ 重要业务逻辑变更
|
||
|
||
**文件**: `services/mcp-server/migrations/024_add_record_type.sql`
|
||
|
||
**目的**: 区分两种计费方式
|
||
- `vm_runtime`: VM运行时间计费(一个Agent = 一条记录,周期性更新)
|
||
- `api_call`: API调用计费(每次调用 = 一条新记录)
|
||
|
||
**操作**:
|
||
```sql
|
||
-- 1. 添加字段
|
||
ALTER TABLE agent_billing_records
|
||
ADD COLUMN IF NOT EXISTS record_type VARCHAR(20) NOT NULL DEFAULT 'vm_runtime';
|
||
|
||
-- 2. 推断现有记录类型
|
||
UPDATE agent_billing_records
|
||
SET record_type = 'api_call'
|
||
WHERE request_id IS NOT NULL
|
||
AND request_id != ''
|
||
AND end_time IS NOT NULL;
|
||
|
||
-- 3. 添加索引
|
||
CREATE INDEX IF NOT EXISTS idx_agent_billing_record_type
|
||
ON agent_billing_records(record_type);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_agent_billing_vm_runtime
|
||
ON agent_billing_records(record_type, end_time)
|
||
WHERE record_type = 'vm_runtime' AND end_time IS NULL;
|
||
```
|
||
|
||
**影响**:
|
||
- 新增业务逻辑字段
|
||
- 周期计费任务将只更新 `record_type='vm_runtime'` 的记录
|
||
|
||
**验证**:
|
||
```sql
|
||
SELECT
|
||
record_type,
|
||
COUNT(*) as count,
|
||
COUNT(CASE WHEN end_time IS NULL THEN 1 END) as running_count,
|
||
COUNT(CASE WHEN end_time IS NOT NULL THEN 1 END) as completed_count
|
||
FROM agent_billing_records
|
||
GROUP BY record_type;
|
||
```
|
||
|
||
**回滚方案**:
|
||
```sql
|
||
ALTER TABLE agent_billing_records DROP COLUMN IF EXISTS record_type;
|
||
DROP INDEX IF EXISTS idx_agent_billing_record_type;
|
||
DROP INDEX IF EXISTS idx_agent_billing_vm_runtime;
|
||
```
|
||
|
||
---
|
||
|
||
## 🚀 执行顺序和依赖关系
|
||
|
||
迁移必须按以下顺序执行(有依赖关系):
|
||
|
||
```
|
||
017 ─────┐
|
||
├──→ 可并行执行
|
||
018 ─────┘
|
||
|
||
019 ─→ 020 ─→ 021 ─→ 022 ─→ 023 ─→ 024
|
||
↑ ↑
|
||
│ │
|
||
修改配额约束 修改计费逻辑(最关键)
|
||
```
|
||
|
||
**推荐分批执行**:
|
||
- **第一批(新功能)**: 017, 018, 019
|
||
- **第二批(数据修正)**: 020, 021, 023
|
||
- **第三批(核心逻辑)**: 022, 024
|
||
|
||
---
|
||
|
||
## ⚙️ 执行步骤
|
||
|
||
### 步骤 1: 备份生产数据库 🔴 必做
|
||
|
||
```bash
|
||
# 使用项目提供的备份脚本
|
||
cd /home/taiji/tools/taiji-AI-PAD
|
||
bash scripts/backup_postgres.sh
|
||
|
||
# 或手动备份
|
||
kubectl exec -n taiji-ai-pad <postgres-pod> -- \
|
||
pg_dump -U postgres taiji_prod > backup_taiji_prod_$(date +%Y%m%d_%H%M%S).dump
|
||
```
|
||
|
||
### 步骤 2: 检查生产环境状态
|
||
|
||
```bash
|
||
# 检查数据库连接
|
||
python services/mcp-server/check_prod_database_status.py
|
||
|
||
# 检查计费健康状态
|
||
python services/mcp-server/check_billing_health.py
|
||
|
||
# 检查配额数据
|
||
python services/mcp-server/check_quota_data.py
|
||
```
|
||
|
||
### 步骤 3: 使用自动同步脚本(推荐)
|
||
|
||
```bash
|
||
# 使用交互式同步脚本
|
||
bash scripts/sync_prod_database.sh
|
||
```
|
||
|
||
该脚本会:
|
||
- ✅ 自动检查K8s集群连接
|
||
- ✅ 显示当前数据库配置
|
||
- ✅ 逐个执行迁移,每步都需要确认
|
||
- ✅ 记录执行日志
|
||
|
||
### 步骤 4: 手动执行(如果需要更细粒度控制)
|
||
|
||
```bash
|
||
# 进入mcp-server Pod
|
||
POD_NAME=$(kubectl get pods -n taiji-ai-pad -l app=mcp-server -o jsonpath='{.items[0].metadata.name}')
|
||
kubectl exec -it -n taiji-ai-pad $POD_NAME -- bash
|
||
|
||
# 切换到migrations目录
|
||
cd /app/migrations
|
||
|
||
# 执行迁移(按顺序)
|
||
python run_017_migration.py
|
||
python run_018_migration.py
|
||
python run_019_migration.py
|
||
python run_020_fix_quota_defaults.py
|
||
# ... 依次执行
|
||
```
|
||
|
||
### 步骤 5: 验证结果
|
||
|
||
```bash
|
||
# 检查表结构
|
||
kubectl exec -n taiji-ai-pad <postgres-pod> -- \
|
||
psql -U postgres -d taiji_prod -c "\d agent_billing_records"
|
||
|
||
# 检查数据完整性
|
||
kubectl exec -n taiji-ai-pad <postgres-pod> -- \
|
||
psql -U postgres -d taiji_prod -c "
|
||
SELECT
|
||
COUNT(*) as total_records,
|
||
COUNT(record_type) as with_record_type,
|
||
COUNT(model_name) as with_model_name,
|
||
COUNT(channel_id) as with_channel_id
|
||
FROM agent_billing_records;
|
||
"
|
||
|
||
# 检查EU和Cost的一致性
|
||
kubectl exec -n taiji-ai-pad <postgres-pod> -- \
|
||
psql -U postgres -d taiji_prod -c "
|
||
SELECT
|
||
COUNT(*) as total,
|
||
COUNT(CASE WHEN ABS(eu_consumed - cost) < 0.0001 THEN 1 END) as consistent,
|
||
COUNT(CASE WHEN ABS(eu_consumed - cost) >= 0.0001 THEN 1 END) as inconsistent
|
||
FROM agent_billing_records
|
||
WHERE cost > 0;
|
||
"
|
||
```
|
||
|
||
### 步骤 6: 重启服务(如果需要)
|
||
|
||
```bash
|
||
# 重启mcp-server以应用新配置
|
||
kubectl rollout restart deployment/mcp-server -n taiji-ai-pad
|
||
|
||
# 等待Pod就绪
|
||
kubectl rollout status deployment/mcp-server -n taiji-ai-pad
|
||
```
|
||
|
||
---
|
||
|
||
## ⚠️ 风险和注意事项
|
||
|
||
### 🔴 高风险操作
|
||
|
||
1. **迁移 022(EU计算逻辑修改)**
|
||
- 会修改所有历史计费记录
|
||
- 建议在业务低峰期执行
|
||
- 必须先备份
|
||
|
||
2. **迁移 020(配额约束)**
|
||
- 会添加检查约束
|
||
- 如果有数据不一致(使用量>配额),迁移会失败
|
||
- 需要先修复数据
|
||
|
||
### 🟡 中风险操作
|
||
|
||
1. **迁移 024(record_type字段)**
|
||
- 修改了计费逻辑
|
||
- 需要确保周期计费任务已更新代码
|
||
|
||
### 🟢 低风险操作
|
||
|
||
- 迁移 017, 018, 019, 021, 023
|
||
- 这些主要是新增字段/表,对现有业务无影响
|
||
|
||
---
|
||
|
||
## 🔄 回滚计划
|
||
|
||
如果迁移后发现问题,按以下步骤回滚:
|
||
|
||
### 快速回滚(恢复备份)
|
||
|
||
```bash
|
||
# 停止服务
|
||
kubectl scale deployment/mcp-server -n taiji-ai-pad --replicas=0
|
||
|
||
# 恢复数据库
|
||
kubectl exec -n taiji-ai-pad <postgres-pod> -- \
|
||
psql -U postgres -c "DROP DATABASE taiji_prod;"
|
||
kubectl exec -n taiji-ai-pad <postgres-pod> -- \
|
||
psql -U postgres -c "CREATE DATABASE taiji_prod;"
|
||
kubectl exec -i -n taiji-ai-pad <postgres-pod> -- \
|
||
psql -U postgres taiji_prod < backup_taiji_prod_20260312_HHMMSS.dump
|
||
|
||
# 重启服务
|
||
kubectl scale deployment/mcp-server -n taiji-ai-pad --replicas=1
|
||
```
|
||
|
||
### 部分回滚(单个迁移)
|
||
|
||
参考每个迁移的"回滚方案"章节,执行对应的 SQL 语句。
|
||
|
||
---
|
||
|
||
## 📊 预期影响评估
|
||
|
||
### 数据量影响
|
||
|
||
```sql
|
||
-- 评估受影响的记录数
|
||
SELECT
|
||
'agent_billing_records' as table_name,
|
||
COUNT(*) as total_records,
|
||
pg_size_pretty(pg_total_relation_size('agent_billing_records')) as table_size
|
||
FROM agent_billing_records
|
||
UNION ALL
|
||
SELECT
|
||
'model_billing_records' as table_name,
|
||
COUNT(*) as total_records,
|
||
pg_size_pretty(pg_total_relation_size('model_billing_records')) as table_size
|
||
FROM model_billing_records;
|
||
```
|
||
|
||
### 停机时间估算
|
||
|
||
- **新表创建(017, 018)**: < 1秒
|
||
- **字段添加(019, 021, 024)**: 1-5秒(取决于表大小)
|
||
- **数据修正(020, 022, 023)**: 1-10分钟(取决于记录数)
|
||
|
||
**建议总停机时间**: 15-30分钟(保守估计)
|
||
|
||
---
|
||
|
||
## ✅ 完成检查清单
|
||
|
||
执行完成后,请确认:
|
||
|
||
- [ ] 所有迁移脚本执行成功,无错误
|
||
- [ ] 新表已创建:`external_data_tools`, `external_toolkits`
|
||
- [ ] 新字段已添加:`model_name`, `record_type`
|
||
- [ ] `eu_consumed` 和 `cost` 数据一致
|
||
- [ ] `channel_id` 缺失值已修复
|
||
- [ ] 配额约束已添加且无冲突
|
||
- [ ] 服务正常启动,无报错
|
||
- [ ] 健康检查通过
|
||
- [ ] 计费任务正常运行
|
||
- [ ] 备份文件已妥善保存
|
||
|
||
---
|
||
|
||
## 📞 问题反馈
|
||
|
||
如果迁移过程中遇到问题,请检查:
|
||
|
||
1. **Pod日志**:
|
||
```bash
|
||
kubectl logs -n taiji-ai-pad deployment/mcp-server --tail=100
|
||
```
|
||
|
||
2. **数据库日志**:
|
||
```bash
|
||
kubectl logs -n taiji-ai-pad <postgres-pod> --tail=100
|
||
```
|
||
|
||
3. **运行健康检查**:
|
||
```bash
|
||
python services/mcp-server/check_billing_health.py
|
||
```
|
||
|
||
---
|
||
|
||
## 📚 相关文档
|
||
|
||
- [计费系统安全性分析](./BILLING_SECURITY_ANALYSIS.md)
|
||
- [数据库配置文档](./config/database-config.md)
|
||
- [计费系统架构文档](./Docs/项目文档/计费管理三维度接口文档.md)
|
||
|
||
---
|
||
|
||
## 📅 变更记录
|
||
|
||
| 日期 | 操作人 | 环境 | 迁移 | 结果 | 备注 |
|
||
|------|--------|------|------|------|------|
|
||
| 2026-03-09~12 | - | 测试环境 | 017-024 | ✅ 成功 | 初次执行 |
|
||
| _待填写_ | _待填写_ | 生产环境 | 017-024 | _待填写_ | _待填写_ |
|
||
|
||
---
|
||
|
||
**最后更新**: 2026-03-12
|
||
**文档版本**: v1.0
|