# CCDI 数据库迁移操作指南

## 概述

本文档提供 CCDI 纪检初核系统数据库迁移的详细操作步骤，包括从开发环境导出数据库和导入到生产/测试环境。

## 脚本说明

项目提供两个独立的脚本：

1. **export_database.sh** - 数据库导出脚本
    - 从开发环境导出数据库
    - 生成表结构和数据文件到 `doc/database/backup/` 文件夹
    - 配置已内置在脚本顶部

2. **import_database.sh** - 数据库导入脚本
    - 从 `doc/database/backup/` 文件夹读取备份文件
    - 导入到指定的目标环境（dev/test/prod）
    - 配置已内置在脚本顶部

## 文件结构

```
项目根目录/
├── export_database.sh              # 导出脚本（配置已内置）
├── import_database.sh              # 导入脚本（配置已内置）
└── doc/
    └── database/
        ├── 数据库迁移操作指南.md   # 本文档
        ├── alter_collation_to_general_ci.sql  # 排序规则修改脚本
        └── backup/                 # 备份文件夹
            ├── .gitkeep
            ├── ccdi_structure.sql  # 表结构（~60KB）
            └── ccdi_data.sql       # 数据文件（~5.7MB）
```

**注意：** 数据库配置已直接内置在脚本中，无需额外的配置文件。

## 前置条件

### 必需工具

- MySQL 客户端工具（包含 mysqldump 和 mysql 命令）
- Bash shell 环境（Windows 用户可使用 Git Bash）
- 网络访问权限（能连接源数据库和目标数据库）

### 检查工具是否安装

```bash
mysqldump --version
mysql --version
```

如果未安装，请根据操作系统安装 MySQL 客户端：

- **Windows**: 安装 MySQL Community Server
- **Linux (Ubuntu/Debian)**: `sudo apt-get install mysql-client`
- **Linux (CentOS/RHEL)**: `sudo yum install mysql`
- **macOS**: `brew install mysql-client`

## 配置步骤

### 1. 修改导出脚本配置

编辑 `export_database.sh` 脚本顶部配置：

```bash
# 源数据库配置（开发环境）
DB_HOST="116.62.17.81"           # 数据库地址
DB_PORT="3306"                   # 数据库端口
DB_USER="root"                   # 数据库用户名
DB_PASS="Kfcx@1234"              # 数据库密码
DB_NAME="ccdi"                   # 数据库名称
```

### 2. 修改导入脚本配置

编辑 `import_database.sh` 脚本顶部配置：

**开发环境:**

```bash
DEV_DB_HOST="116.62.17.81"       # 开发环境数据库地址
DEV_DB_PORT="3306"               # 数据库端口
DEV_DB_USER="root"               # 数据库用户名
DEV_DB_PASS="Kfcx@1234"          # 数据库密码
DEV_DB_NAME="ccdi"               # 数据库名称
```

**测试环境:**

```bash
TEST_DB_HOST="your_test_host"    # 测试环境数据库地址
TEST_DB_PORT="3306"              # 数据库端口
TEST_DB_USER="your_test_user"    # 数据库用户名
TEST_DB_PASS="your_test_password" # 数据库密码
TEST_DB_NAME="ccdi"              # 数据库名称
```

**生产环境:**

```bash
PROD_DB_HOST="your_prod_host"    # 生产环境数据库地址
PROD_DB_PORT="3306"              # 数据库端口
PROD_DB_USER="your_prod_user"    # 数据库用户名
PROD_DB_PASS="your_prod_password" # 数据库密码
PROD_DB_NAME="ccdi"              # 数据库名称
```

### 3. 验证配置

查看配置是否正确：

```bash
# 查看导出脚本配置
head -20 export_database.sh

# 查看导入脚本配置
head -30 import_database.sh
```

## 数据库导出

### 执行导出

```bash
# 方式1: 使用默认命令
./export_database.sh

# 方式2: 显式指定命令
./export_database.sh export
```

### 预期输出

```
[INFO] ========== 开始导出数据库 ==========
[INFO] 配置文件加载成功
[INFO] mysqldump 命令检查通过
[INFO] 开始导出表结构...
[INFO] 表结构导出成功: doc/database/backup/ccdi_structure.sql
[INFO] 文件大小: 60K
[INFO] 开始导出数据...
[INFO] 数据导出成功: doc/database/backup/ccdi_data.sql
[INFO] 文件大小: 5.7M
[INFO] 验证导出文件...
[INFO] 导出文件验证通过
[INFO] 表结构文件: doc/database/backup/ccdi_structure.sql (60K)
[INFO] 数据文件: doc/database/backup/ccdi_data.sql (5.7M)
[INFO] ========== 数据库导出完成 ==========
[INFO] 使用 ./import_database.sh <env> 导入到目标环境
```

### 验证导出文件

**1. 检查文件是否存在**

```bash
ls -lh doc/database/backup/
```

应该看到：

- `ccdi_structure.sql` - 表结构文件（~60KB）
- `ccdi_data.sql` - 数据文件（~5.7MB）

**2. 检查字符集声明**

```bash
head -20 doc/database/backup/ccdi_structure.sql
```

应该包含：

```sql
SET NAMES utf8mb4;
SET CHARACTER SET utf8mb4;
```

**3. 检查文件内容**

```bash
# 查看表数量
grep "CREATE TABLE" doc/database/backup/ccdi_structure.sql | wc -l

# 查看数据量（INSERT 语句数量）
grep "INSERT" doc/database/backup/ccdi_data.sql | wc -l
```

## 数据库导入

### 准备工作

**1. 确认目标数据库已创建**

连接到目标数据库服务器：

```bash
mysql -h 目标IP -P 3306 -u 用户名 -p
```

创建数据库（如果不存在）：

```sql
CREATE DATABASE ccdi CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
```

**2. 确认用户权限**

目标数据库用户需要以下权限：

- CREATE、ALTER、DROP（创建和修改表）
- INSERT、UPDATE、DELETE（数据操作）
- INDEX（创建索引）
- REFERENCES（外键约束）

### 导入到测试环境

```bash
./import_database.sh test
```

### 导入到生产环境

```bash
./import_database.sh production
```

或简写：

```bash
./import_database.sh prod
```

### 导入到开发环境

```bash
./import_database.sh dev
```

### 预期输出

```
[INFO] ========== 开始导入数据库到 test 环境 ==========
[INFO] 配置文件加载成功
[INFO] mysql 命令检查通过
[INFO] 检查备份文件...
[INFO] 备份文件检查通过
[INFO] 表结构文件: doc/database/backup/ccdi_structure.sql (60K)
[INFO] 数据文件: doc/database/backup/ccdi_data.sql (5.7M)
[INFO] 导入表结构到 test 环境: XXX:3306/ccdi
[INFO] 表结构导入成功
[INFO] 导入数据到 test 环境: XXX:3306/ccdi
[INFO] 数据导入成功
[INFO] 验证导入结果...
[INFO] 目标数据库表数量: 42
[INFO] sys_user 表数据行数: XX
[INFO] 数据库字符集: utf8mb4
[INFO] ========== 数据库导入完成 ==========
```

## 导入后验证

### 1. 验证表数量

连接到目标数据库：

```bash
mysql -h 目标IP -P 3306 -u 用户名 -p ccdi
```

查询表数量：

```sql
SELECT COUNT(*) FROM information_schema.tables
WHERE table_schema='ccdi';
```

对比源数据库和目标数据库的表数量是否一致。

### 2. 验证数据行数

查询各表数据行数：

```sql
SELECT table_name, table_rows
FROM information_schema.tables
WHERE table_schema='ccdi'
ORDER BY table_rows DESC
LIMIT 20;
```

对比源数据库和目标数据库的关键表行数。

### 3. 验证字符集

检查数据库字符集：

```sql
SHOW CREATE DATABASE ccdi;
```

应该显示：`DEFAULT CHARACTER SET utf8mb4`

检查表字符集：

```sql
SHOW CREATE TABLE sys_user;
```

应该显示：`ENGINE=InnoDB DEFAULT CHARSET=utf8mb4`

### 4. 验证中文数据

查询包含中文的数据：

```sql
-- 查询用户表
SELECT user_name, nick_name FROM sys_user LIMIT 10;

-- 查询字典数据
SELECT dict_label, dict_value FROM sys_dict_data LIMIT 10;

-- 查询业务表
SELECT name, person_type FROM ccdi_biz_intermediary LIMIT 10;
```

确保中文字符显示正常，无乱码。

### 5. 应用程序连接测试

修改应用程序配置文件连接到目标数据库，启动应用程序进行功能测试。

## 完整迁移流程示例

### 场景：从开发环境迁移到生产环境

**1. 配置数据库连接**

```bash
# 编辑导出脚本配置（开发环境）
nano export_database.sh
# 修改脚本顶部的 DB_HOST, DB_USER, DB_PASS 等配置

# 编辑导入脚本配置（生产环境）
nano import_database.sh
# 修改脚本顶部的 PROD_DB_HOST, PROD_DB_USER, PROD_DB_PASS 等配置
```

**2. 导出数据库**

```bash
./export_database.sh
```

**3. 验证导出文件**

```bash
ls -lh doc/database/backup/
head -20 doc/database/backup/ccdi_structure.sql
```

**4. 先在测试环境验证**

```bash
# 确保已在 import_database.sh 中配置测试环境
./import_database.sh test
```

**5. 验证测试环境**

- 连接测试数据库验证数据
- 应用程序连接测试环境进行功能测试

**6. 导入到生产环境**

```bash
./import_database.sh prod
```

**7. 验证生产环境**

- 连接生产数据库验证数据
- 应用程序连接生产环境进行功能测试

**8. 完成迁移**

## 常见问题

### 1. mysqldump: command not found

**原因**: MySQL 客户端未安装或未添加到 PATH

**解决**:

- 安装 MySQL 客户端工具
- 或使用完整路径：`/usr/bin/mysqldump`

### 2. 数据库连接失败

**错误信息**: 连接被拒绝或认证失败

**解决**:

- 检查脚本顶部的数据库配置是否正确
- 使用 mysql 命令手动测试连接
- 检查防火墙规则

### 3. 导入时字符集乱码

**原因**: 未正确指定字符集

**解决**:

- 确保导出文件包含字符集声明
- 导入命令添加 `--default-character-set=utf8mb4` 参数
- 脚本已自动处理，如仍有问题请检查数据库默认字符集

### 5. 外键约束失败

**错误信息**: `ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails`

**解决**:

- 脚本已自动添加 `SET FOREIGN_KEY_CHECKS=0;` 和 `SET FOREIGN_KEY_CHECKS=1;`
- 如仍有问题，请检查数据完整性

### 6. 数据包过大

**错误信息**: `ERROR 1153 (08S01): Got a packet bigger than 'max_allowed_packet' bytes`

**解决**:

- 配置文件中的 `MAX_ALLOWED_PACKET=512M` 已处理此问题
- 如数据量特别大，可增大此值

### 7. 权限不足

**错误信息**: `ERROR 1044 (42000): Access denied for user`

**解决**:

- 使用具有足够权限的用户（如 root）
- 或授予用户必要权限

### 8. 备份文件不存在

**错误信息**: `表结构文件不存在: doc/database/backup/ccdi_structure.sql`

**解决**:

- 先执行导出：`./export_database.sh`
- 检查 backup 文件夹中是否有 SQL 文件

## 回滚方案

如果迁移失败或出现问题：

1. **保留源数据库**: 不要删除开发环境数据库
2. **重新迁移**: 修复问题后重新执行迁移流程
3. **从备份恢复**: 如生产环境有备份，可从备份恢复

## 注意事项

1. **安全性**:
    - 数据库配置已内置在脚本中，包含敏感信息
    - 不要将脚本提交到公开的版本控制系统
    - 迁移完成后建议删除脚本中的密码或使用占位符

2. **性能**:
    - 大数据库导出/导入可能需要较长时间
    - 建议在低峰期执行迁移
    - 确保有足够的磁盘空间

3. **数据一致性**:
    - 导出期间源数据库应避免写入操作
    - 或使用 `--single-transaction` 参数（已包含）

4. **字符集**:
    - 确保所有步骤都使用 utf8mb4 字符集
    - 验证阶段重点检查中文数据
    - 表结构文件不再包含显式的 COLLATE 配置（使用默认 utf8mb4_general_ci）

5. **脚本配置**:
    - 首次使用前必须在脚本顶部配置数据库信息
    - 三个环境的配置是独立的，可以只配置需要的环境
    - 修改配置后无需其他操作即可使用

## 技术支持

如遇到问题：

1. 检查本文档的常见问题部分
2. 查看脚本执行的错误信息
3. 检查数据库连接和权限
4. 查看数据库日志

## 相关文件

- 导出脚本: `export_database.sh`（配置已内置）
- 导入脚本: `import_database.sh`（配置已内置）
- 表结构文件: `doc/database/backup/ccdi_structure.sql`
- 数据文件: `doc/database/backup/ccdi_data.sql`
- 排序规则修改脚本: `doc/database/alter_collation_to_general_ci.sql`
- 设计文档: `docs/plans/2026-02-28-database-migration-design.md`
