Files
urbanLifeline/.kiro/specs/urbanlifeline-to-pigx-migration/database-migration.md
2026-01-14 15:42:26 +08:00

571 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 数据库迁移脚本指南PostgreSQL → MySQL
## 1. 概述
本文档提供了将 urbanLifeline 数据库从 PostgreSQL 迁移到 MySQLpigx 平台)的完整脚本和指南。
## 2. 数据类型映射
| PostgreSQL | MySQL | 说明 |
|-----------|-------|------|
| VARCHAR(n) | VARCHAR(n) | 字符串 |
| TEXT | TEXT | 长文本 |
| INTEGER | INT | 整数 |
| BIGINT | BIGINT | 长整数 |
| BOOLEAN | TINYINT(1) | 布尔值 |
| TIMESTAMPTZ | DATETIME | 时间戳 |
| JSONB | JSON | JSON数据 |
| NUMERIC(p,s) | DECIMAL(p,s) | 小数 |
| VARCHAR(n)[] | JSON | 数组转JSON |
| SERIAL | INT AUTO_INCREMENT | 自增 |
## 3. pigx-dify 模块数据库脚本
### 3.1 智能体表 (tb_agent)
```sql
-- 智能体配置表
CREATE TABLE `tb_agent` (
`optsn` varchar(50) NOT NULL COMMENT '流水号',
`agent_id` varchar(50) NOT NULL COMMENT '智能体ID',
`name` varchar(50) NOT NULL COMMENT '智能体名称',
`description` varchar(500) DEFAULT NULL COMMENT '智能体描述',
`link` varchar(500) DEFAULT NULL COMMENT '智能体url',
`api_key` varchar(500) NOT NULL COMMENT 'dify智能体APIKEY',
`is_outer` tinyint(1) DEFAULT '0' COMMENT '是否是对外智能体,未登录可用',
`introduce` varchar(500) NOT NULL COMMENT '引导词',
`prompt_cards` json DEFAULT NULL COMMENT '提示卡片数组 [{file_id:, prompt:}]',
`category` varchar(50) NOT NULL COMMENT '分类',
`tenant_id` bigint NOT NULL DEFAULT '1' COMMENT '租户ID',
`creator` varchar(50) DEFAULT NULL COMMENT '创建者',
`updater` varchar(50) DEFAULT NULL COMMENT '更新者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`delete_time` datetime DEFAULT NULL COMMENT '删除时间',
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除',
PRIMARY KEY (`agent_id`),
UNIQUE KEY `uk_optsn` (`optsn`),
UNIQUE KEY `uk_api_key` (`api_key`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI智能体配置表';
```
### 3.2 对话表 (tb_chat)
```sql
-- AI智能体对话表
CREATE TABLE `tb_chat` (
`optsn` varchar(50) NOT NULL COMMENT '流水号',
`chat_id` varchar(50) NOT NULL COMMENT '对话ID',
`agent_id` varchar(50) NOT NULL COMMENT '智能体ID',
`user_id` varchar(50) NOT NULL COMMENT '用户ID',
`user_type` tinyint(1) NOT NULL DEFAULT '1' COMMENT '用户类型 1-系统内部人员 0-系统外部人员',
`title` varchar(500) NOT NULL COMMENT '对话标题',
`channel` varchar(50) DEFAULT 'agent' COMMENT '对话渠道 agent、wechat',
`tenant_id` bigint NOT NULL DEFAULT '1' COMMENT '租户ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`delete_time` datetime DEFAULT NULL COMMENT '删除时间',
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除',
PRIMARY KEY (`chat_id`),
UNIQUE KEY `uk_optsn` (`optsn`),
KEY `idx_agent_id` (`agent_id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI智能体对话表';
```
### 3.3 聊天消息表 (tb_chat_message)
```sql
-- AI智能体对话消息表
CREATE TABLE `tb_chat_message` (
`optsn` varchar(50) NOT NULL COMMENT '流水号',
`message_id` varchar(50) NOT NULL COMMENT '消息ID',
`dify_message_id` varchar(100) DEFAULT NULL COMMENT 'Dify消息ID',
`chat_id` varchar(50) NOT NULL COMMENT '对话ID',
`role` varchar(50) NOT NULL COMMENT '角色user-用户/ai-智能体/recipient-来客',
`content` text NOT NULL COMMENT '消息内容',
`files` json DEFAULT NULL COMMENT '文件id数组',
`comment` varchar(50) DEFAULT NULL COMMENT '评价',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`delete_time` datetime DEFAULT NULL COMMENT '删除时间',
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除',
PRIMARY KEY (`message_id`),
UNIQUE KEY `uk_optsn` (`optsn`),
KEY `idx_chat_id` (`chat_id`),
KEY `idx_dify_message_id` (`dify_message_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI智能体对话消息表';
```
### 3.4 知识库表 (tb_knowledge)
```sql
-- 知识库配置表
CREATE TABLE `tb_knowledge` (
`optsn` varchar(50) NOT NULL COMMENT '流水号',
`knowledge_id` varchar(50) NOT NULL COMMENT '知识库ID',
`title` varchar(255) NOT NULL COMMENT '知识库标题',
`avatar` varchar(255) DEFAULT NULL COMMENT '知识库头像',
`description` varchar(500) DEFAULT NULL COMMENT '知识库描述',
`dify_dataset_id` varchar(100) DEFAULT NULL COMMENT 'Dify知识库IDDataset ID',
`dify_indexing_technique` varchar(50) DEFAULT 'high_quality' COMMENT 'Dify索引方式high_quality/economy',
`embedding_model` varchar(100) DEFAULT NULL COMMENT '向量模型名称',
`embedding_model_provider` varchar(100) DEFAULT NULL COMMENT '向量模型提供商',
`rerank_model` varchar(100) DEFAULT NULL COMMENT 'Rerank模型名称',
`rerank_model_provider` varchar(100) DEFAULT NULL COMMENT 'Rerank模型提供商',
`reranking_enable` tinyint(1) DEFAULT '0' COMMENT '是否启用Rerank',
`retrieval_top_k` int DEFAULT '2' COMMENT '检索Top K返回前K个结果',
`retrieval_score_threshold` decimal(3,2) DEFAULT '0.00' COMMENT '检索分数阈值0.00-1.00',
`document_count` int DEFAULT '0' COMMENT '文档数量',
`total_chunks` int DEFAULT '0' COMMENT '总分段数',
`service` varchar(50) DEFAULT NULL COMMENT '所属服务 workcase、bidding',
`project_id` varchar(50) DEFAULT NULL COMMENT 'bidding所属项目ID',
`category` varchar(50) DEFAULT NULL COMMENT '所属分类',
`tenant_id` bigint NOT NULL DEFAULT '1' COMMENT '租户ID',
`creator` varchar(50) NOT NULL COMMENT '创建者用户ID',
`dept_path` varchar(50) DEFAULT NULL COMMENT '创建者部门路径',
`updater` varchar(50) DEFAULT NULL COMMENT '更新者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`delete_time` datetime DEFAULT NULL COMMENT '删除时间',
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除',
PRIMARY KEY (`optsn`),
UNIQUE KEY `uk_knowledge_id` (`knowledge_id`),
UNIQUE KEY `uk_dify_dataset_id` (`dify_dataset_id`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='知识库配置表';
```
### 3.5 知识库文件表 (tb_knowledge_file)
```sql
-- 知识库文件表
CREATE TABLE `tb_knowledge_file` (
`optsn` varchar(50) NOT NULL COMMENT '流水号',
`knowledge_id` varchar(50) NOT NULL COMMENT '知识库ID',
`file_root_id` varchar(50) NOT NULL COMMENT '文件根ID',
`file_id` varchar(50) NOT NULL COMMENT '文件ID',
`dify_file_id` varchar(50) NOT NULL COMMENT 'dify文件ID',
`version` int NOT NULL DEFAULT '1' COMMENT '文件版本',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`delete_time` datetime DEFAULT NULL COMMENT '删除时间',
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除',
PRIMARY KEY (`optsn`),
UNIQUE KEY `uk_knowledge_file` (`knowledge_id`, `file_id`),
KEY `idx_file_root_id` (`file_root_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='知识库文件表';
```
## 4. pigx-app-server 模块数据库脚本
### 4.1 工单表 (tb_workcase)
```sql
-- 工单表
CREATE TABLE `tb_workcase` (
`optsn` varchar(50) NOT NULL COMMENT '流水号',
`workcase_id` varchar(50) NOT NULL COMMENT '工单ID',
`room_id` varchar(50) NOT NULL COMMENT '聊天室ID',
`user_id` varchar(50) NOT NULL COMMENT '来客ID',
`username` varchar(200) NOT NULL COMMENT '来客姓名',
`phone` varchar(20) NOT NULL COMMENT '来客电话',
`type` varchar(50) NOT NULL COMMENT '故障类型',
`device` varchar(50) DEFAULT NULL COMMENT '设备名称',
`device_code` varchar(50) DEFAULT NULL COMMENT '设备代码',
`device_name_plate` varchar(50) DEFAULT NULL COMMENT '设备名称牌',
`device_name_plate_img` varchar(50) NOT NULL COMMENT '设备名称牌图片',
`address` varchar(1000) DEFAULT NULL COMMENT '现场地址',
`description` varchar(1000) DEFAULT NULL COMMENT '故障描述',
`imgs` json DEFAULT NULL COMMENT '工单图片id数组',
`emergency` varchar(50) NOT NULL DEFAULT 'normal' COMMENT '紧急程度 normal-普通 emergency-紧急',
`status` varchar(50) NOT NULL DEFAULT 'pending' COMMENT '状态 pending-待处理 processing-处理中 done-已完成',
`processor` varchar(50) DEFAULT NULL COMMENT '处理人',
`tenant_id` bigint NOT NULL DEFAULT '1' COMMENT '租户ID',
`creator` varchar(50) NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`delete_time` datetime DEFAULT NULL COMMENT '删除时间',
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除',
PRIMARY KEY (`workcase_id`),
UNIQUE KEY `uk_room_id` (`room_id`),
UNIQUE KEY `uk_optsn` (`optsn`),
KEY `idx_user_id` (`user_id`),
KEY `idx_status` (`status`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='工单表';
```
### 4.2 聊天室表 (tb_chat_room)
```sql
-- IM聊天室表
CREATE TABLE `tb_chat_room` (
`optsn` varchar(50) NOT NULL COMMENT '流水号',
`room_id` varchar(50) NOT NULL COMMENT '聊天室ID',
`workcase_id` varchar(50) DEFAULT NULL COMMENT '关联工单ID',
`room_name` varchar(200) NOT NULL COMMENT '聊天室名称',
`room_type` varchar(20) NOT NULL DEFAULT 'workcase' COMMENT '聊天室类型workcase-工单客服',
`status` varchar(20) NOT NULL DEFAULT 'active' COMMENT '状态active-活跃 closed-已关闭 archived-已归档',
`guest_id` varchar(50) NOT NULL COMMENT '来客ID创建者',
`guest_name` varchar(100) NOT NULL COMMENT '来客姓名',
`ai_session_id` varchar(50) DEFAULT NULL COMMENT 'AI对话会话ID从ai.tb_chat同步',
`message_count` int NOT NULL DEFAULT '0' COMMENT '消息总数',
`device_code` varchar(50) NOT NULL COMMENT '设备代码',
`last_message_time` datetime DEFAULT NULL COMMENT '最后消息时间',
`last_message` text DEFAULT NULL COMMENT '最后一条消息内容',
`comment_level` int DEFAULT '0' COMMENT '服务评分1-5',
`closed_by` varchar(50) DEFAULT NULL COMMENT '关闭人',
`closed_time` datetime DEFAULT NULL COMMENT '关闭时间',
`tenant_id` bigint NOT NULL DEFAULT '1' COMMENT '租户ID',
`creator` varchar(50) NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`delete_time` datetime DEFAULT NULL COMMENT '删除时间',
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除',
PRIMARY KEY (`room_id`),
UNIQUE KEY `uk_workcase_id` (`workcase_id`),
UNIQUE KEY `uk_optsn` (`optsn`),
KEY `idx_guest` (`guest_id`, `status`),
KEY `idx_last_message_time` (`last_message_time`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='IM聊天室表一个工单对应一个聊天室';
```
### 4.3 聊天室成员表 (tb_chat_room_member)
```sql
-- 聊天室成员表
CREATE TABLE `tb_chat_room_member` (
`optsn` varchar(50) NOT NULL COMMENT '流水号',
`member_id` varchar(50) NOT NULL COMMENT '成员记录ID',
`room_id` varchar(50) NOT NULL COMMENT '聊天室ID',
`user_id` varchar(50) NOT NULL COMMENT '用户ID来客ID或员工ID',
`user_type` varchar(20) NOT NULL COMMENT '用户类型guest-来客 staff-客服 ai-AI助手',
`user_name` varchar(100) NOT NULL COMMENT '用户名称',
`status` varchar(20) NOT NULL DEFAULT 'active' COMMENT '状态active-活跃 left-已离开 removed-被移除',
`unread_count` int NOT NULL DEFAULT '0' COMMENT '未读消息数',
`last_read_time` datetime DEFAULT NULL COMMENT '最后阅读时间',
`last_read_msg_id` varchar(50) DEFAULT NULL COMMENT '最后阅读的消息ID',
`join_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '加入时间',
`leave_time` datetime DEFAULT NULL COMMENT '离开时间',
`creator` varchar(50) NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`member_id`),
UNIQUE KEY `uk_room_user` (`room_id`, `user_id`),
KEY `idx_room_status` (`room_id`, `status`),
KEY `idx_user` (`user_id`, `user_type`, `status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='聊天室成员表';
```
### 4.4 聊天室消息表 (tb_chat_room_message)
```sql
-- 聊天室消息表
CREATE TABLE `tb_chat_room_message` (
`optsn` varchar(50) NOT NULL COMMENT '流水号',
`message_id` varchar(50) NOT NULL COMMENT '消息ID',
`room_id` varchar(50) NOT NULL COMMENT '聊天室ID',
`sender_id` varchar(50) NOT NULL COMMENT '发送者ID',
`sender_type` varchar(20) NOT NULL COMMENT '发送者类型guest-来客 agent-客服 ai-AI助手 system-系统消息',
`sender_name` varchar(100) NOT NULL COMMENT '发送者名称',
`message_type` varchar(20) NOT NULL DEFAULT 'text' COMMENT '消息类型',
`content` text NOT NULL COMMENT '消息内容',
`files` json DEFAULT NULL COMMENT '附件文件ID数组',
`content_extra` json DEFAULT NULL COMMENT '扩展内容(会议链接、引用信息等)',
`reply_to_msg_id` varchar(50) DEFAULT NULL COMMENT '回复的消息ID',
`is_ai_message` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否AI消息',
`ai_message_id` varchar(50) DEFAULT NULL COMMENT 'AI原始消息ID',
`status` varchar(20) NOT NULL DEFAULT 'sent' COMMENT '状态',
`read_count` int NOT NULL DEFAULT '0' COMMENT '已读人数',
`send_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '发送时间',
`creator` varchar(50) NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`message_id`),
KEY `idx_room_time` (`room_id`, `send_time`),
KEY `idx_sender` (`sender_id`, `sender_type`),
KEY `idx_ai_message` (`ai_message_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='IM聊天消息表';
```
### 4.5 视频会议表 (tb_video_meeting)
```sql
-- Jitsi Meet视频会议表
CREATE TABLE `tb_video_meeting` (
`optsn` varchar(50) NOT NULL COMMENT '流水号',
`meeting_id` varchar(50) NOT NULL COMMENT '会议ID也是Jitsi房间名',
`room_id` varchar(50) NOT NULL COMMENT '关联聊天室ID',
`workcase_id` varchar(50) NOT NULL COMMENT '关联工单ID',
`meeting_name` varchar(200) NOT NULL COMMENT '会议名称',
`meeting_password` varchar(50) DEFAULT NULL COMMENT '会议密码',
`description` varchar(500) DEFAULT NULL COMMENT '会议描述',
`jwt_token` text DEFAULT NULL COMMENT 'JWT Token用于身份验证',
`jitsi_room_name` varchar(200) NOT NULL COMMENT 'Jitsi房间名',
`jitsi_server_url` varchar(500) NOT NULL DEFAULT 'https://meet.jit.si' COMMENT 'Jitsi服务器地址',
`status` varchar(20) NOT NULL DEFAULT 'scheduled' COMMENT '状态',
`creator_type` varchar(20) NOT NULL COMMENT '创建者类型',
`creator_name` varchar(100) NOT NULL COMMENT '创建者名称',
`participant_count` int NOT NULL DEFAULT '0' COMMENT '参与人数',
`max_participants` int DEFAULT '10' COMMENT '最大参与人数',
`start_time` datetime NOT NULL COMMENT '定义会议开始时间',
`end_time` datetime NOT NULL COMMENT '定义会议结束时间',
`advance` int DEFAULT '5' COMMENT '提前入会时间(分钟)',
`actual_start_time` datetime DEFAULT NULL COMMENT '真正会议开始时间',
`actual_end_time` datetime DEFAULT NULL COMMENT '真正会议结束时间',
`duration_seconds` int DEFAULT '0' COMMENT '会议时长(秒)',
`iframe_url` text DEFAULT NULL COMMENT 'iframe嵌入URL',
`config` json DEFAULT NULL COMMENT 'Jitsi配置项',
`tenant_id` bigint NOT NULL DEFAULT '1' COMMENT '租户ID',
`creator` varchar(50) NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`delete_time` datetime DEFAULT NULL COMMENT '删除时间',
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除',
PRIMARY KEY (`meeting_id`),
UNIQUE KEY `uk_jitsi_room_name` (`jitsi_room_name`),
KEY `idx_room` (`room_id`, `status`),
KEY `idx_workcase` (`workcase_id`, `status`),
KEY `idx_create_time` (`create_time`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Jitsi Meet视频会议表';
```
## 5. 数据迁移步骤
### 5.1 准备工作
```bash
# 1. 导出 PostgreSQL 数据
pg_dump -h localhost -p 5432 -U postgres -d urbanlifeline \
--data-only \
--column-inserts \
--no-owner \
--no-privileges \
--no-tablespaces \
> urbanlifeline_data.sql
# 2. 创建 MySQL 数据库
mysql -u root -p -e "CREATE DATABASE pigx_dify DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;"
```
### 5.2 执行表结构创建
```bash
# 执行所有建表语句
mysql -u root -p pigx_dify < create_tables.sql
```
### 5.3 数据转换脚本
```python
#!/usr/bin/env python3
# convert_data.py - PostgreSQL 到 MySQL 数据转换脚本
import re
import json
def convert_postgresql_to_mysql(input_file, output_file):
with open(input_file, 'r', encoding='utf-8') as f:
content = f.read()
# 替换 PostgreSQL 特有语法
replacements = [
# 布尔值转换
(r'\btrue\b', '1'),
(r'\bfalse\b', '0'),
# 时间戳转换
(r"now\(\)", "CURRENT_TIMESTAMP"),
# 数组转JSON
(r"'{([^}]*)}'::\w+\[\]", lambda m: f"'{json.dumps(m.group(1).split(',') if m.group(1) else [])}'"),
# Schema 去除
(r'\b(workcase|ai|sys|message|bidding)\\.', ''),
]
for pattern, replacement in replacements:
if callable(replacement):
content = re.sub(pattern, replacement, content)
else:
content = re.sub(pattern, replacement, content, flags=re.IGNORECASE)
# 添加租户ID到每个INSERT语句
content = add_tenant_id(content)
with open(output_file, 'w', encoding='utf-8') as f:
f.write(content)
def add_tenant_id(content):
"""为所有INSERT语句添加tenant_id字段"""
lines = content.split('\n')
result = []
for line in lines:
if line.startswith('INSERT INTO'):
# 检查表是否需要tenant_id
if any(table in line for table in ['tb_agent', 'tb_chat', 'tb_workcase', 'tb_chat_room']):
# 在VALUES前添加tenant_id字段
line = re.sub(
r'(\([^)]+)\)',
r'\1, tenant_id)',
line, count=1
)
# 在值列表中添加1作为默认租户ID
line = re.sub(
r'VALUES\s*\(([^)]+)\)',
r'VALUES (\1, 1)',
line
)
result.append(line)
return '\n'.join(result)
if __name__ == '__main__':
convert_postgresql_to_mysql('urbanlifeline_data.sql', 'pigx_data.sql')
print("数据转换完成!")
```
### 5.4 导入数据到 MySQL
```bash
# 导入转换后的数据
mysql -u root -p pigx_dify < pigx_data.sql
# 验证数据
mysql -u root -p pigx_dify -e "
SELECT COUNT(*) FROM tb_agent;
SELECT COUNT(*) FROM tb_chat;
SELECT COUNT(*) FROM tb_workcase;
"
```
## 6. 添加租户字段指南
### 6.1 需要添加 tenant_id 的表
所有业务表都需要添加 `tenant_id` 字段:
- tb_agent
- tb_chat
- tb_chat_message通过chat关联获取
- tb_knowledge
- tb_workcase
- tb_chat_room
- tb_video_meeting
### 6.2 添加租户字段的SQL模板
```sql
-- 为现有表添加租户字段(如果表已存在)
ALTER TABLE `tb_agent`
ADD COLUMN `tenant_id` BIGINT NOT NULL DEFAULT 1 COMMENT '租户ID' AFTER `category`,
ADD INDEX `idx_tenant_id` (`tenant_id`);
-- 更新现有数据的租户ID默认为1
UPDATE tb_agent SET tenant_id = 1 WHERE tenant_id IS NULL;
```
### 6.3 MyBatis-Plus 配置
```java
// 实体类添加租户字段
@TableField(fill = FieldFill.INSERT)
private Long tenantId;
// 自动填充处理器
@Component
public class MybatisPlusMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
PigxUser user = SecurityUtils.getUser();
this.strictInsertFill(metaObject, "tenantId", Long.class, user.getTenantId());
}
}
// 租户拦截器配置
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
@Override
public Expression getTenantId() {
return new LongValue(SecurityUtils.getUser().getTenantId());
}
@Override
public String getTenantIdColumn() {
return "tenant_id";
}
}));
return interceptor;
}
```
## 7. 验证和测试
### 7.1 数据完整性检查
```sql
-- 检查数据迁移完整性
SELECT
'tb_agent' AS table_name,
COUNT(*) AS record_count
FROM tb_agent
UNION ALL
SELECT 'tb_chat', COUNT(*) FROM tb_chat
UNION ALL
SELECT 'tb_workcase', COUNT(*) FROM tb_workcase;
-- 检查租户ID设置
SELECT
tenant_id,
COUNT(*) AS record_count
FROM tb_agent
GROUP BY tenant_id;
```
### 7.2 索引优化
```sql
-- 添加常用查询索引
ALTER TABLE tb_chat ADD INDEX idx_user_agent (user_id, agent_id);
ALTER TABLE tb_workcase ADD INDEX idx_create_time (create_time DESC);
ALTER TABLE tb_chat_message ADD INDEX idx_chat_time (chat_id, create_time DESC);
```
## 8. 回滚方案
如果迁移失败,可以使用以下方式回滚:
```bash
# 备份当前MySQL数据
mysqldump -u root -p pigx_dify > backup_before_migration.sql
# 如需回滚
mysql -u root -p -e "DROP DATABASE pigx_dify; CREATE DATABASE pigx_dify;"
mysql -u root -p pigx_dify < backup_before_migration.sql
```
## 9. 注意事项
1. **字符集**:确保 MySQL 使用 utf8mb4 字符集
2. **时区**:注意 PostgreSQL 的 TIMESTAMPTZ 转换为 MySQL DATETIME 可能有时区差异
3. **数组类型**PostgreSQL 的数组类型需要转换为 JSON
4. **事务**:大批量数据导入时注意事务大小
5. **权限**:确保 MySQL 用户有足够权限创建表和索引
6. **外键**:本脚本未创建外键约束,如需要可后续添加
## 10. 迁移清单
- [ ] 导出 PostgreSQL 数据
- [ ] 创建 MySQL 数据库和表结构
- [ ] 执行数据转换脚本
- [ ] 导入数据到 MySQL
- [ ] 添加租户字段和索引
- [ ] 验证数据完整性
- [ ] 测试查询性能
- [ ] 配置 MyBatis-Plus 租户拦截器
- [ ] 执行应用集成测试
- [ ] 准备回滚方案