Files
urbanLifeline/.kiro/specs/urbanlifeline-to-pigx-migration/database-migration.md

571 lines
23 KiB
Markdown
Raw Normal View History

2026-01-14 15:42:26 +08:00
# 数据库迁移脚本指南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 租户拦截器
- [ ] 执行应用集成测试
- [ ] 准备回滚方案