571 lines
23 KiB
Markdown
571 lines
23 KiB
Markdown
# 数据库迁移脚本指南(PostgreSQL → MySQL)
|
||
|
||
## 1. 概述
|
||
|
||
本文档提供了将 urbanLifeline 数据库从 PostgreSQL 迁移到 MySQL(pigx 平台)的完整脚本和指南。
|
||
|
||
## 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知识库ID(Dataset 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 租户拦截器
|
||
- [ ] 执行应用集成测试
|
||
- [ ] 准备回滚方案 |