1249 lines
29 KiB
Markdown
1249 lines
29 KiB
Markdown
|
|
# 数据库迁移实施计划
|
|||
|
|
|
|||
|
|
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|||
|
|
|
|||
|
|
**Goal:** 创建自动化脚本完成 CCDI 数据库的完整导出和导入,包括表结构和数据,确保字符集正确无乱码
|
|||
|
|
|
|||
|
|
**Architecture:** 使用 mysqldump 命令导出数据库,分离表结构和数据为两个 SQL 文件,通过 Bash 脚本自动化管理导出和导入流程,配置文件管理多环境数据库连接信息
|
|||
|
|
|
|||
|
|
**Tech Stack:** Bash 脚本、mysqldump/mysql 命令行工具、UTF-8/utf8mb4 字符集
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 1: 创建配置文件模板和安全措施
|
|||
|
|
|
|||
|
|
**Files:**
|
|||
|
|
- Create: `db_config.conf.template`
|
|||
|
|
- Modify: `.gitignore`
|
|||
|
|
|
|||
|
|
**Step 1: 创建配置文件模板**
|
|||
|
|
|
|||
|
|
创建 `db_config.conf.template` 文件:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 数据库迁移配置文件模板
|
|||
|
|
# 使用方法:复制此文件为 db_config.conf 并填写实际值
|
|||
|
|
|
|||
|
|
# 源数据库配置(开发环境)
|
|||
|
|
SOURCE_DB_HOST=116.62.17.81
|
|||
|
|
SOURCE_DB_PORT=3306
|
|||
|
|
SOURCE_DB_USER=root
|
|||
|
|
SOURCE_DB_PASS=Kfcx@1234
|
|||
|
|
SOURCE_DB_NAME=ccdi
|
|||
|
|
|
|||
|
|
# 生产环境数据库配置
|
|||
|
|
PROD_DB_HOST=your_production_host
|
|||
|
|
PROD_DB_PORT=3306
|
|||
|
|
PROD_DB_USER=your_production_user
|
|||
|
|
PROD_DB_PASS=your_production_password
|
|||
|
|
PROD_DB_NAME=ccdi
|
|||
|
|
|
|||
|
|
# 测试环境数据库配置(可选)
|
|||
|
|
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
|
|||
|
|
|
|||
|
|
# 导出文件配置
|
|||
|
|
BACKUP_DIR=doc/database/backup
|
|||
|
|
STRUCTURE_FILE=ccdi_structure.sql
|
|||
|
|
DATA_FILE=ccdi_data.sql
|
|||
|
|
|
|||
|
|
# mysqldump 参数配置
|
|||
|
|
CHARACTER_SET=utf8mb4
|
|||
|
|
MAX_ALLOWED_PACKET=512M
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 2: 更新 .gitignore 文件**
|
|||
|
|
|
|||
|
|
在 `.gitignore` 文件末尾添加:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
# 数据库配置文件(包含敏感信息)
|
|||
|
|
db_config.conf
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 3: 提交配置模板**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
git add db_config.conf.template .gitignore
|
|||
|
|
git commit -m "feat: 添加数据库迁移配置模板和安全措施"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 2: 创建备份目录结构
|
|||
|
|
|
|||
|
|
**Files:**
|
|||
|
|
- Create: `doc/database/backup/.gitkeep`
|
|||
|
|
|
|||
|
|
**Step 1: 创建备份目录**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
mkdir -p doc/database/backup
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 2: 创建 .gitkeep 文件保持目录**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
touch doc/database/backup/.gitkeep
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 3: 提交目录结构**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
git add doc/database/backup/.gitkeep
|
|||
|
|
git commit -m "feat: 创建数据库备份目录结构"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 3: 创建自动化导出脚本(框架和导出功能)
|
|||
|
|
|
|||
|
|
**Files:**
|
|||
|
|
- Create: `export_database.sh`
|
|||
|
|
|
|||
|
|
**Step 1: 创建脚本文件并添加基本框架**
|
|||
|
|
|
|||
|
|
创建 `export_database.sh` 文件:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
#!/bin/bash
|
|||
|
|
|
|||
|
|
# CCDI 数据库迁移自动化脚本
|
|||
|
|
# 功能:数据库导出和导入自动化
|
|||
|
|
|
|||
|
|
set -e # 遇到错误立即退出
|
|||
|
|
|
|||
|
|
# 颜色定义
|
|||
|
|
RED='\033[0;31m'
|
|||
|
|
GREEN='\033[0;32m'
|
|||
|
|
YELLOW='\033[1;33m'
|
|||
|
|
NC='\033[0m' # No Color
|
|||
|
|
|
|||
|
|
# 日志函数
|
|||
|
|
log_info() {
|
|||
|
|
echo -e "${GREEN}[INFO]${NC} $1"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
log_warn() {
|
|||
|
|
echo -e "${YELLOW}[WARN]${NC} $1"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
log_error() {
|
|||
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 脚本目录
|
|||
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|||
|
|
CONFIG_FILE="${SCRIPT_DIR}/db_config.conf"
|
|||
|
|
|
|||
|
|
# 检查配置文件
|
|||
|
|
check_config() {
|
|||
|
|
if [ ! -f "$CONFIG_FILE" ]; then
|
|||
|
|
log_error "配置文件不存在: $CONFIG_FILE"
|
|||
|
|
log_info "请先复制配置模板: cp db_config.conf.template db_config.conf"
|
|||
|
|
log_info "然后编辑 db_config.conf 填写实际数据库连接信息"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# 加载配置文件
|
|||
|
|
source "$CONFIG_FILE"
|
|||
|
|
log_info "配置文件加载成功"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 检查 mysqldump 命令
|
|||
|
|
check_mysqldump() {
|
|||
|
|
if ! command -v mysqldump &> /dev/null; then
|
|||
|
|
log_error "mysqldump 命令未找到"
|
|||
|
|
log_info "请安装 MySQL 客户端工具"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
log_info "mysqldump 命令检查通过"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 创建备份目录
|
|||
|
|
create_backup_dir() {
|
|||
|
|
if [ ! -d "$BACKUP_DIR" ]; then
|
|||
|
|
mkdir -p "$BACKUP_DIR"
|
|||
|
|
log_info "创建备份目录: $BACKUP_DIR"
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 导出表结构
|
|||
|
|
export_structure() {
|
|||
|
|
log_info "开始导出表结构..."
|
|||
|
|
|
|||
|
|
local output_file="${BACKUP_DIR}/${STRUCTURE_FILE}"
|
|||
|
|
|
|||
|
|
# 创建临时文件
|
|||
|
|
local temp_file=$(mktemp)
|
|||
|
|
|
|||
|
|
# 导出表结构到临时文件
|
|||
|
|
mysqldump -h "$SOURCE_DB_HOST" \
|
|||
|
|
-P "$SOURCE_DB_PORT" \
|
|||
|
|
-u "$SOURCE_DB_USER" \
|
|||
|
|
-p"$SOURCE_DB_PASS" \
|
|||
|
|
--no-data \
|
|||
|
|
--skip-triggers \
|
|||
|
|
--skip-add-drop-table \
|
|||
|
|
--default-character-set=$CHARACTER_SET \
|
|||
|
|
--single-transaction \
|
|||
|
|
--max_allowed_packet=$MAX_ALLOWED_PACKET \
|
|||
|
|
"$SOURCE_DB_NAME" > "$temp_file" 2>/dev/null
|
|||
|
|
|
|||
|
|
if [ $? -eq 0 ]; then
|
|||
|
|
# 添加字符集声明到文件头部
|
|||
|
|
{
|
|||
|
|
echo "-- CCDI 数据库表结构"
|
|||
|
|
echo "-- 导出时间: $(date '+%Y-%m-%d %H:%M:%S')"
|
|||
|
|
echo "-- 源数据库: ${SOURCE_DB_HOST}:${SOURCE_DB_PORT}/${SOURCE_DB_NAME}"
|
|||
|
|
echo "-- 字符集: ${CHARACTER_SET}"
|
|||
|
|
echo ""
|
|||
|
|
echo "SET NAMES utf8mb4;"
|
|||
|
|
echo "SET CHARACTER SET utf8mb4;"
|
|||
|
|
echo "SET GLOBAL character_set_client=utf8mb4;"
|
|||
|
|
echo "SET GLOBAL character_set_connection=utf8mb4;"
|
|||
|
|
echo "SET GLOBAL character_set_results=utf8mb4;"
|
|||
|
|
echo ""
|
|||
|
|
cat "$temp_file"
|
|||
|
|
} > "$output_file"
|
|||
|
|
|
|||
|
|
rm -f "$temp_file"
|
|||
|
|
log_info "表结构导出成功: $output_file"
|
|||
|
|
log_info "文件大小: $(du -h "$output_file" | cut -f1)"
|
|||
|
|
else
|
|||
|
|
rm -f "$temp_file"
|
|||
|
|
log_error "表结构导出失败"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 导出数据
|
|||
|
|
export_data() {
|
|||
|
|
log_info "开始导出数据..."
|
|||
|
|
|
|||
|
|
local output_file="${BACKUP_DIR}/${DATA_FILE}"
|
|||
|
|
|
|||
|
|
# 创建临时文件
|
|||
|
|
local temp_file=$(mktemp)
|
|||
|
|
|
|||
|
|
# 导出数据到临时文件
|
|||
|
|
mysqldump -h "$SOURCE_DB_HOST" \
|
|||
|
|
-P "$SOURCE_DB_PORT" \
|
|||
|
|
-u "$SOURCE_DB_USER" \
|
|||
|
|
-p"$SOURCE_DB_PASS" \
|
|||
|
|
--no-create-info \
|
|||
|
|
--skip-triggers \
|
|||
|
|
--default-character-set=$CHARACTER_SET \
|
|||
|
|
--single-transaction \
|
|||
|
|
--complete-insert \
|
|||
|
|
--extended-insert \
|
|||
|
|
--max_allowed_packet=$MAX_ALLOWED_PACKET \
|
|||
|
|
"$SOURCE_DB_NAME" > "$temp_file" 2>/dev/null
|
|||
|
|
|
|||
|
|
if [ $? -eq 0 ]; then
|
|||
|
|
# 添加字符集声明到文件头部
|
|||
|
|
{
|
|||
|
|
echo "-- CCDI 数据库数据"
|
|||
|
|
echo "-- 导出时间: $(date '+%Y-%m-%d %H:%M:%S')"
|
|||
|
|
echo "-- 源数据库: ${SOURCE_DB_HOST}:${SOURCE_DB_PORT}/${SOURCE_DB_NAME}"
|
|||
|
|
echo "-- 字符集: ${CHARACTER_SET}"
|
|||
|
|
echo ""
|
|||
|
|
echo "SET NAMES utf8mb4;"
|
|||
|
|
echo "SET CHARACTER SET utf8mb4;"
|
|||
|
|
echo "SET GLOBAL character_set_client=utf8mb4;"
|
|||
|
|
echo "SET GLOBAL character_set_connection=utf8mb4;"
|
|||
|
|
echo "SET GLOBAL character_set_results=utf8mb4;"
|
|||
|
|
echo "SET FOREIGN_KEY_CHECKS=0;"
|
|||
|
|
echo ""
|
|||
|
|
cat "$temp_file"
|
|||
|
|
echo ""
|
|||
|
|
echo "SET FOREIGN_KEY_CHECKS=1;"
|
|||
|
|
} > "$output_file"
|
|||
|
|
|
|||
|
|
rm -f "$temp_file"
|
|||
|
|
log_info "数据导出成功: $output_file"
|
|||
|
|
log_info "文件大小: $(du -h "$output_file" | cut -f1)"
|
|||
|
|
else
|
|||
|
|
rm -f "$temp_file"
|
|||
|
|
log_error "数据导出失败"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 验证导出文件
|
|||
|
|
verify_export() {
|
|||
|
|
log_info "验证导出文件..."
|
|||
|
|
|
|||
|
|
local structure_file="${BACKUP_DIR}/${STRUCTURE_FILE}"
|
|||
|
|
local data_file="${BACKUP_DIR}/${DATA_FILE}"
|
|||
|
|
|
|||
|
|
# 检查文件是否存在
|
|||
|
|
if [ ! -f "$structure_file" ]; then
|
|||
|
|
log_error "表结构文件不存在: $structure_file"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
if [ ! -f "$data_file" ]; then
|
|||
|
|
log_error "数据文件不存在: $data_file"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# 检查字符集声明
|
|||
|
|
if ! grep -q "SET NAMES utf8mb4" "$structure_file"; then
|
|||
|
|
log_error "表结构文件缺少字符集声明"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
if ! grep -q "SET NAMES utf8mb4" "$data_file"; then
|
|||
|
|
log_error "数据文件缺少字符集声明"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
log_info "导出文件验证通过"
|
|||
|
|
log_info "表结构文件: $structure_file ($(du -h "$structure_file" | cut -f1))"
|
|||
|
|
log_info "数据文件: $data_file ($(du -h "$data_file" | cut -f1))"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 导出数据库
|
|||
|
|
export_database() {
|
|||
|
|
log_info "========== 开始导出数据库 =========="
|
|||
|
|
|
|||
|
|
check_config
|
|||
|
|
check_mysqldump
|
|||
|
|
create_backup_dir
|
|||
|
|
export_structure
|
|||
|
|
export_data
|
|||
|
|
verify_export
|
|||
|
|
|
|||
|
|
log_info "========== 数据库导出完成 =========="
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 使用帮助
|
|||
|
|
show_usage() {
|
|||
|
|
echo "用法: $0 <command>"
|
|||
|
|
echo ""
|
|||
|
|
echo "命令:"
|
|||
|
|
echo " export 导出数据库"
|
|||
|
|
echo " help 显示帮助信息"
|
|||
|
|
echo ""
|
|||
|
|
echo "示例:"
|
|||
|
|
echo " $0 export # 导出数据库到 doc/database/backup/ 目录"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 主函数
|
|||
|
|
main() {
|
|||
|
|
case "$1" in
|
|||
|
|
export)
|
|||
|
|
export_database
|
|||
|
|
;;
|
|||
|
|
help|--help|-h)
|
|||
|
|
show_usage
|
|||
|
|
;;
|
|||
|
|
*)
|
|||
|
|
log_error "未知命令: $1"
|
|||
|
|
show_usage
|
|||
|
|
exit 1
|
|||
|
|
;;
|
|||
|
|
esac
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 执行主函数
|
|||
|
|
main "$@"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 2: 设置脚本执行权限**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
chmod +x export_database.sh
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 3: 提交导出脚本**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
git add export_database.sh
|
|||
|
|
git commit -m "feat: 创建数据库导出自动化脚本"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 4: 执行数据库导出
|
|||
|
|
|
|||
|
|
**Files:**
|
|||
|
|
- Generate: `doc/database/backup/ccdi_structure.sql`
|
|||
|
|
- Generate: `doc/database/backup/ccdi_data.sql`
|
|||
|
|
|
|||
|
|
**Step 1: 创建配置文件**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cp db_config.conf.template db_config.conf
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 2: 验证配置文件内容**
|
|||
|
|
|
|||
|
|
检查 `db_config.conf` 文件确保源数据库配置正确:
|
|||
|
|
```bash
|
|||
|
|
cat db_config.conf | grep "SOURCE_DB"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
预期输出:
|
|||
|
|
```
|
|||
|
|
SOURCE_DB_HOST=116.62.17.81
|
|||
|
|
SOURCE_DB_PORT=3306
|
|||
|
|
SOURCE_DB_USER=root
|
|||
|
|
SOURCE_DB_PASS=Kfcx@1234
|
|||
|
|
SOURCE_DB_NAME=ccdi
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 3: 执行导出脚本**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
./export_database.sh export
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
预期输出:
|
|||
|
|
```
|
|||
|
|
[INFO] 配置文件加载成功
|
|||
|
|
[INFO] mysqldump 命令检查通过
|
|||
|
|
[INFO] 开始导出表结构...
|
|||
|
|
[INFO] 表结构导出成功: doc/database/backup/ccdi_structure.sql
|
|||
|
|
[INFO] 文件大小: XXX
|
|||
|
|
[INFO] 开始导出数据...
|
|||
|
|
[INFO] 数据导出成功: doc/database/backup/ccdi_data.sql
|
|||
|
|
[INFO] 文件大小: XXX
|
|||
|
|
[INFO] 验证导出文件...
|
|||
|
|
[INFO] 导出文件验证通过
|
|||
|
|
[INFO] ========== 数据库导出完成 ==========
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 4: 验证导出文件**
|
|||
|
|
|
|||
|
|
检查表结构文件头部:
|
|||
|
|
```bash
|
|||
|
|
head -20 doc/database/backup/ccdi_structure.sql
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
预期输出应包含:
|
|||
|
|
```sql
|
|||
|
|
-- CCDI 数据库表结构
|
|||
|
|
-- 导出时间: 2026-02-28 XX:XX:XX
|
|||
|
|
-- 源数据库: 116.62.17.81:3306/ccdi
|
|||
|
|
-- 字符集: utf8mb4
|
|||
|
|
|
|||
|
|
SET NAMES utf8mb4;
|
|||
|
|
SET CHARACTER SET utf8mb4;
|
|||
|
|
...
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
检查数据文件头部:
|
|||
|
|
```bash
|
|||
|
|
head -20 doc/database/backup/ccdi_data.sql
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
预期输出应包含:
|
|||
|
|
```sql
|
|||
|
|
-- CCDI 数据库数据
|
|||
|
|
-- 导出时间: 2026-02-28 XX:XX:XX
|
|||
|
|
-- 源数据库: 116.62.17.81:3306/ccdi
|
|||
|
|
-- 字符集: utf8mb4
|
|||
|
|
|
|||
|
|
SET NAMES utf8mb4;
|
|||
|
|
SET CHARACTER SET utf8mb4;
|
|||
|
|
SET FOREIGN_KEY_CHECKS=0;
|
|||
|
|
...
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 5: 检查文件大小**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
ls -lh doc/database/backup/
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
预期输出应显示两个文件的大小。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 5: 添加导入功能到脚本
|
|||
|
|
|
|||
|
|
**Files:**
|
|||
|
|
- Modify: `export_database.sh` (添加导入函数)
|
|||
|
|
|
|||
|
|
**Step 1: 在脚本中添加导入函数**
|
|||
|
|
|
|||
|
|
在 `export_database.sh` 文件的 `verify_export()` 函数后添加以下函数:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
|
|||
|
|
# 导入表结构
|
|||
|
|
import_structure() {
|
|||
|
|
local env_type=$1
|
|||
|
|
local db_host db_port db_user db_pass db_name
|
|||
|
|
|
|||
|
|
case "$env_type" in
|
|||
|
|
production|prod)
|
|||
|
|
db_host="$PROD_DB_HOST"
|
|||
|
|
db_port="$PROD_DB_PORT"
|
|||
|
|
db_user="$PROD_DB_USER"
|
|||
|
|
db_pass="$PROD_DB_PASS"
|
|||
|
|
db_name="$PROD_DB_NAME"
|
|||
|
|
;;
|
|||
|
|
test)
|
|||
|
|
db_host="$TEST_DB_HOST"
|
|||
|
|
db_port="$TEST_DB_PORT"
|
|||
|
|
db_user="$TEST_DB_USER"
|
|||
|
|
db_pass="$TEST_DB_PASS"
|
|||
|
|
db_name="$TEST_DB_NAME"
|
|||
|
|
;;
|
|||
|
|
*)
|
|||
|
|
log_error "未知的环境类型: $env_type"
|
|||
|
|
exit 1
|
|||
|
|
;;
|
|||
|
|
esac
|
|||
|
|
|
|||
|
|
log_info "导入表结构到 ${env_type} 环境: ${db_host}:${db_port}/${db_name}"
|
|||
|
|
|
|||
|
|
local structure_file="${BACKUP_DIR}/${STRUCTURE_FILE}"
|
|||
|
|
|
|||
|
|
if [ ! -f "$structure_file" ]; then
|
|||
|
|
log_error "表结构文件不存在: $structure_file"
|
|||
|
|
log_info "请先执行导出: ./export_database.sh export"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# 导入表结构
|
|||
|
|
mysql -h "$db_host" \
|
|||
|
|
-P "$db_port" \
|
|||
|
|
-u "$db_user" \
|
|||
|
|
-p"$db_pass" \
|
|||
|
|
--default-character-set=$CHARACTER_SET \
|
|||
|
|
"$db_name" < "$structure_file" 2>/dev/null
|
|||
|
|
|
|||
|
|
if [ $? -eq 0 ]; then
|
|||
|
|
log_info "表结构导入成功"
|
|||
|
|
else
|
|||
|
|
log_error "表结构导入失败"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 导入数据
|
|||
|
|
import_data() {
|
|||
|
|
local env_type=$1
|
|||
|
|
local db_host db_port db_user db_pass db_name
|
|||
|
|
|
|||
|
|
case "$env_type" in
|
|||
|
|
production|prod)
|
|||
|
|
db_host="$PROD_DB_HOST"
|
|||
|
|
db_port="$PROD_DB_PORT"
|
|||
|
|
db_user="$PROD_DB_USER"
|
|||
|
|
db_pass="$PROD_DB_PASS"
|
|||
|
|
db_name="$PROD_DB_NAME"
|
|||
|
|
;;
|
|||
|
|
test)
|
|||
|
|
db_host="$TEST_DB_HOST"
|
|||
|
|
db_port="$TEST_DB_PORT"
|
|||
|
|
db_user="$TEST_DB_USER"
|
|||
|
|
db_pass="$TEST_DB_PASS"
|
|||
|
|
db_name="$TEST_DB_NAME"
|
|||
|
|
;;
|
|||
|
|
*)
|
|||
|
|
log_error "未知的环境类型: $env_type"
|
|||
|
|
exit 1
|
|||
|
|
;;
|
|||
|
|
esac
|
|||
|
|
|
|||
|
|
log_info "导入数据到 ${env_type} 环境: ${db_host}:${db_port}/${db_name}"
|
|||
|
|
|
|||
|
|
local data_file="${BACKUP_DIR}/${DATA_FILE}"
|
|||
|
|
|
|||
|
|
if [ ! -f "$data_file" ]; then
|
|||
|
|
log_error "数据文件不存在: $data_file"
|
|||
|
|
log_info "请先执行导出: ./export_database.sh export"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# 导入数据
|
|||
|
|
mysql -h "$db_host" \
|
|||
|
|
-P "$db_port" \
|
|||
|
|
-u "$db_user" \
|
|||
|
|
-p"$db_pass" \
|
|||
|
|
--default-character-set=$CHARACTER_SET \
|
|||
|
|
"$db_name" < "$data_file" 2>/dev/null
|
|||
|
|
|
|||
|
|
if [ $? -eq 0 ]; then
|
|||
|
|
log_info "数据导入成功"
|
|||
|
|
else
|
|||
|
|
log_error "数据导入失败"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 验证导入结果
|
|||
|
|
verify_import() {
|
|||
|
|
local env_type=$1
|
|||
|
|
local db_host db_port db_user db_pass db_name
|
|||
|
|
|
|||
|
|
case "$env_type" in
|
|||
|
|
production|prod)
|
|||
|
|
db_host="$PROD_DB_HOST"
|
|||
|
|
db_port="$PROD_DB_PORT"
|
|||
|
|
db_user="$PROD_DB_USER"
|
|||
|
|
db_pass="$PROD_DB_PASS"
|
|||
|
|
db_name="$PROD_DB_NAME"
|
|||
|
|
;;
|
|||
|
|
test)
|
|||
|
|
db_host="$TEST_DB_HOST"
|
|||
|
|
db_port="$TEST_DB_PORT"
|
|||
|
|
db_user="$TEST_DB_USER"
|
|||
|
|
db_pass="$TEST_DB_PASS"
|
|||
|
|
db_name="$TEST_DB_NAME"
|
|||
|
|
;;
|
|||
|
|
*)
|
|||
|
|
log_error "未知的环境类型: $env_type"
|
|||
|
|
exit 1
|
|||
|
|
;;
|
|||
|
|
esac
|
|||
|
|
|
|||
|
|
log_info "验证导入结果..."
|
|||
|
|
|
|||
|
|
# 查询表数量
|
|||
|
|
local table_count=$(mysql -h "$db_host" \
|
|||
|
|
-P "$db_port" \
|
|||
|
|
-u "$db_user" \
|
|||
|
|
-p"$db_pass" \
|
|||
|
|
--default-character-set=$CHARACTER_SET \
|
|||
|
|
-N -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='$db_name';" "$db_name" 2>/dev/null)
|
|||
|
|
|
|||
|
|
log_info "目标数据库表数量: $table_count"
|
|||
|
|
|
|||
|
|
# 查询关键表行数(示例:sys_user 表)
|
|||
|
|
local user_count=$(mysql -h "$db_host" \
|
|||
|
|
-P "$db_port" \
|
|||
|
|
-u "$db_user" \
|
|||
|
|
-p"$db_pass" \
|
|||
|
|
--default-character-set=$CHARACTER_SET \
|
|||
|
|
-N -e "SELECT COUNT(*) FROM sys_user;" "$db_name" 2>/dev/null)
|
|||
|
|
|
|||
|
|
log_info "sys_user 表数据行数: $user_count"
|
|||
|
|
|
|||
|
|
# 检查数据库字符集
|
|||
|
|
local db_charset=$(mysql -h "$db_host" \
|
|||
|
|
-P "$db_port" \
|
|||
|
|
-u "$db_user" \
|
|||
|
|
-p"$db_pass" \
|
|||
|
|
--default-character-set=$CHARACTER_SET \
|
|||
|
|
-N -e "SELECT DEFAULT_CHARACTER_SET_NAME FROM information_schema.schemata WHERE schema_name='$db_name';" 2>/dev/null)
|
|||
|
|
|
|||
|
|
log_info "数据库字符集: $db_charset"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 导入数据库
|
|||
|
|
import_database() {
|
|||
|
|
local env_type=$1
|
|||
|
|
|
|||
|
|
if [ -z "$env_type" ]; then
|
|||
|
|
log_error "请指定目标环境: production 或 test"
|
|||
|
|
log_info "用法: $0 import [production|test]"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
log_info "========== 开始导入数据库到 ${env_type} 环境 =========="
|
|||
|
|
|
|||
|
|
check_config
|
|||
|
|
import_structure "$env_type"
|
|||
|
|
import_data "$env_type"
|
|||
|
|
verify_import "$env_type"
|
|||
|
|
|
|||
|
|
log_info "========== 数据库导入完成 =========="
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 2: 更新 show_usage() 函数**
|
|||
|
|
|
|||
|
|
替换 `show_usage()` 函数为:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 使用帮助
|
|||
|
|
show_usage() {
|
|||
|
|
echo "用法: $0 <command> [options]"
|
|||
|
|
echo ""
|
|||
|
|
echo "命令:"
|
|||
|
|
echo " export 导出数据库"
|
|||
|
|
echo " import <env> 导入数据库到指定环境"
|
|||
|
|
echo " help 显示帮助信息"
|
|||
|
|
echo ""
|
|||
|
|
echo "环境:"
|
|||
|
|
echo " production, prod 生产环境"
|
|||
|
|
echo " test 测试环境"
|
|||
|
|
echo ""
|
|||
|
|
echo "示例:"
|
|||
|
|
echo " $0 export # 导出数据库到 doc/database/backup/ 目录"
|
|||
|
|
echo " $0 import test # 导入数据库到测试环境"
|
|||
|
|
echo " $0 import prod # 导入数据库到生产环境"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 3: 更新 main() 函数**
|
|||
|
|
|
|||
|
|
替换 `main()` 函数为:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 主函数
|
|||
|
|
main() {
|
|||
|
|
case "$1" in
|
|||
|
|
export)
|
|||
|
|
export_database
|
|||
|
|
;;
|
|||
|
|
import)
|
|||
|
|
import_database "$2"
|
|||
|
|
;;
|
|||
|
|
help|--help|-h)
|
|||
|
|
show_usage
|
|||
|
|
;;
|
|||
|
|
*)
|
|||
|
|
log_error "未知命令: $1"
|
|||
|
|
show_usage
|
|||
|
|
exit 1
|
|||
|
|
;;
|
|||
|
|
esac
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 4: 提交导入功能**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
git add export_database.sh
|
|||
|
|
git commit -m "feat: 添加数据库导入功能到自动化脚本"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 6: 创建操作指南文档
|
|||
|
|
|
|||
|
|
**Files:**
|
|||
|
|
- Create: `doc/database/backup/export_guide.md`
|
|||
|
|
|
|||
|
|
**Step 1: 创建操作指南文档**
|
|||
|
|
|
|||
|
|
创建 `doc/database/backup/export_guide.md` 文件:
|
|||
|
|
|
|||
|
|
```markdown
|
|||
|
|
# CCDI 数据库迁移操作指南
|
|||
|
|
|
|||
|
|
## 概述
|
|||
|
|
|
|||
|
|
本文档提供 CCDI 纪检初核系统数据库迁移的详细操作步骤,包括从开发环境导出数据库和导入到生产/测试环境。
|
|||
|
|
|
|||
|
|
## 前置条件
|
|||
|
|
|
|||
|
|
### 必需工具
|
|||
|
|
- MySQL 客户端工具(包含 mysqldump 和 mysql 命令)
|
|||
|
|
- Bash shell 环境
|
|||
|
|
- 网络访问权限(能连接源数据库和目标数据库)
|
|||
|
|
|
|||
|
|
### 检查 mysqldump 是否安装
|
|||
|
|
```bash
|
|||
|
|
mysqldump --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. 创建配置文件
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 复制配置模板
|
|||
|
|
cp db_config.conf.template db_config.conf
|
|||
|
|
|
|||
|
|
# 编辑配置文件
|
|||
|
|
nano db_config.conf # 或使用其他编辑器
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 填写配置信息
|
|||
|
|
|
|||
|
|
编辑 `db_config.conf` 文件,填写以下信息:
|
|||
|
|
|
|||
|
|
**源数据库(开发环境):**
|
|||
|
|
- `SOURCE_DB_HOST`: 开发环境数据库地址
|
|||
|
|
- `SOURCE_DB_PORT`: 数据库端口(默认 3306)
|
|||
|
|
- `SOURCE_DB_USER`: 数据库用户名
|
|||
|
|
- `SOURCE_DB_PASS`: 数据库密码
|
|||
|
|
- `SOURCE_DB_NAME`: 数据库名称(ccdi)
|
|||
|
|
|
|||
|
|
**生产环境数据库:**
|
|||
|
|
- `PROD_DB_HOST`: 生产环境数据库地址
|
|||
|
|
- `PROD_DB_PORT`: 数据库端口
|
|||
|
|
- `PROD_DB_USER`: 生产环境数据库用户名
|
|||
|
|
- `PROD_DB_PASS`: 生产环境数据库密码
|
|||
|
|
- `PROD_DB_NAME`: 数据库名称(ccdi)
|
|||
|
|
|
|||
|
|
**测试环境数据库(可选):**
|
|||
|
|
- `TEST_DB_HOST`: 测试环境数据库地址
|
|||
|
|
- `TEST_DB_PORT`: 数据库端口
|
|||
|
|
- `TEST_DB_USER`: 测试环境数据库用户名
|
|||
|
|
- `TEST_DB_PASS`: 测试环境数据库密码
|
|||
|
|
- `TEST_DB_NAME`: 数据库名称(ccdi)
|
|||
|
|
|
|||
|
|
### 3. 验证配置
|
|||
|
|
|
|||
|
|
检查配置文件格式:
|
|||
|
|
```bash
|
|||
|
|
cat db_config.conf | grep -E "^[A-Z]"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
确保所有必需的配置项都已填写。
|
|||
|
|
|
|||
|
|
## 数据库导出
|
|||
|
|
|
|||
|
|
### 执行导出
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
./export_database.sh export
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 预期输出
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
[INFO] 配置文件加载成功
|
|||
|
|
[INFO] mysqldump 命令检查通过
|
|||
|
|
[INFO] 开始导出表结构...
|
|||
|
|
[INFO] 表结构导出成功: doc/database/backup/ccdi_structure.sql
|
|||
|
|
[INFO] 文件大小: XXX
|
|||
|
|
[INFO] 开始导出数据...
|
|||
|
|
[INFO] 数据导出成功: doc/database/backup/ccdi_data.sql
|
|||
|
|
[INFO] 文件大小: XXX
|
|||
|
|
[INFO] 验证导出文件...
|
|||
|
|
[INFO] 导出文件验证通过
|
|||
|
|
[INFO] ========== 数据库导出完成 ==========
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 验证导出文件
|
|||
|
|
|
|||
|
|
**1. 检查文件是否存在**
|
|||
|
|
```bash
|
|||
|
|
ls -lh doc/database/backup/
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
应该看到:
|
|||
|
|
- `ccdi_structure.sql` - 表结构文件
|
|||
|
|
- `ccdi_data.sql` - 数据文件
|
|||
|
|
|
|||
|
|
**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
|
|||
|
|
./export_database.sh import test
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 导入到生产环境
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
./export_database.sh import production
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
或简写:
|
|||
|
|
```bash
|
|||
|
|
./export_database.sh import prod
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 预期输出
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
[INFO] ========== 开始导入数据库到 test 环境 ==========
|
|||
|
|
[INFO] 导入表结构到 test 环境: XXX:3306/ccdi
|
|||
|
|
[INFO] 表结构导入成功
|
|||
|
|
[INFO] 导入数据到 test 环境: XXX:3306/ccdi
|
|||
|
|
[INFO] 数据导入成功
|
|||
|
|
[INFO] 验证导入结果...
|
|||
|
|
[INFO] 目标数据库表数量: XX
|
|||
|
|
[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;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
确保中文字符显示正常,无乱码。
|
|||
|
|
|
|||
|
|
### 5. 应用程序连接测试
|
|||
|
|
|
|||
|
|
修改应用程序配置文件连接到目标数据库,启动应用程序进行功能测试。
|
|||
|
|
|
|||
|
|
## 完整迁移流程示例
|
|||
|
|
|
|||
|
|
### 场景:从开发环境迁移到生产环境
|
|||
|
|
|
|||
|
|
**1. 配置数据库连接**
|
|||
|
|
```bash
|
|||
|
|
cp db_config.conf.template db_config.conf
|
|||
|
|
nano db_config.conf
|
|||
|
|
# 填写开发环境和生产环境数据库信息
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**2. 导出数据库**
|
|||
|
|
```bash
|
|||
|
|
./export_database.sh export
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**3. 验证导出文件**
|
|||
|
|
```bash
|
|||
|
|
ls -lh doc/database/backup/
|
|||
|
|
head -20 doc/database/backup/ccdi_structure.sql
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**4. 先在测试环境验证**
|
|||
|
|
```bash
|
|||
|
|
./export_database.sh import test
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**5. 验证测试环境**
|
|||
|
|
- 连接测试数据库验证数据
|
|||
|
|
- 应用程序连接测试环境进行功能测试
|
|||
|
|
|
|||
|
|
**6. 导入到生产环境**
|
|||
|
|
```bash
|
|||
|
|
./export_database.sh import production
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**7. 验证生产环境**
|
|||
|
|
- 连接生产数据库验证数据
|
|||
|
|
- 应用程序连接生产环境进行功能测试
|
|||
|
|
|
|||
|
|
**8. 完成迁移**
|
|||
|
|
|
|||
|
|
## 常见问题
|
|||
|
|
|
|||
|
|
### 1. mysqldump: command not found
|
|||
|
|
|
|||
|
|
**原因**: MySQL 客户端未安装或未添加到 PATH
|
|||
|
|
|
|||
|
|
**解决**:
|
|||
|
|
- 安装 MySQL 客户端工具
|
|||
|
|
- 或使用完整路径:`/usr/bin/mysqldump`
|
|||
|
|
|
|||
|
|
### 2. 配置文件不存在
|
|||
|
|
|
|||
|
|
**错误信息**: `配置文件不存在: db_config.conf`
|
|||
|
|
|
|||
|
|
**解决**:
|
|||
|
|
```bash
|
|||
|
|
cp db_config.conf.template db_config.conf
|
|||
|
|
# 编辑 db_config.conf 填写实际配置
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 连接数据库失败
|
|||
|
|
|
|||
|
|
**可能原因**:
|
|||
|
|
- 数据库地址、端口、用户名或密码错误
|
|||
|
|
- 防火墙阻止连接
|
|||
|
|
- 数据库服务未启动
|
|||
|
|
|
|||
|
|
**解决**:
|
|||
|
|
- 检查配置文件中的连接信息
|
|||
|
|
- 使用 mysql 命令手动测试连接
|
|||
|
|
- 检查防火墙规则
|
|||
|
|
|
|||
|
|
### 4. 导入时字符集乱码
|
|||
|
|
|
|||
|
|
**原因**: 未正确指定字符集
|
|||
|
|
|
|||
|
|
**解决**:
|
|||
|
|
- 确保导出文件包含字符集声明
|
|||
|
|
- 导入命令添加 `--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)
|
|||
|
|
- 或授予用户必要权限
|
|||
|
|
|
|||
|
|
## 回滚方案
|
|||
|
|
|
|||
|
|
如果迁移失败或出现问题:
|
|||
|
|
|
|||
|
|
1. **保留源数据库**: 不要删除开发环境数据库
|
|||
|
|
2. **重新迁移**: 修复问题后重新执行迁移流程
|
|||
|
|
3. **从备份恢复**: 如生产环境有备份,可从备份恢复
|
|||
|
|
|
|||
|
|
## 注意事项
|
|||
|
|
|
|||
|
|
1. **安全性**:
|
|||
|
|
- `db_config.conf` 包含敏感信息,已添加到 `.gitignore`
|
|||
|
|
- 不要将配置文件提交到版本控制系统
|
|||
|
|
- 迁移完成后建议删除配置文件中的密码
|
|||
|
|
|
|||
|
|
2. **性能**:
|
|||
|
|
- 大数据库导出/导入可能需要较长时间
|
|||
|
|
- 建议在低峰期执行迁移
|
|||
|
|
- 确保有足够的磁盘空间
|
|||
|
|
|
|||
|
|
3. **数据一致性**:
|
|||
|
|
- 导出期间源数据库应避免写入操作
|
|||
|
|
- 或使用 `--single-transaction` 参数(已包含)
|
|||
|
|
|
|||
|
|
4. **字符集**:
|
|||
|
|
- 确保所有步骤都使用 utf8mb4 字符集
|
|||
|
|
- 验证阶段重点检查中文数据
|
|||
|
|
|
|||
|
|
## 技术支持
|
|||
|
|
|
|||
|
|
如遇到问题:
|
|||
|
|
1. 检查本文档的常见问题部分
|
|||
|
|
2. 查看脚本执行的错误信息
|
|||
|
|
3. 检查数据库连接和权限
|
|||
|
|
4. 查看数据库日志
|
|||
|
|
|
|||
|
|
## 相关文件
|
|||
|
|
|
|||
|
|
- 自动化脚本: `export_database.sh`
|
|||
|
|
- 配置模板: `db_config.conf.template`
|
|||
|
|
- 实际配置: `db_config.conf`
|
|||
|
|
- 表结构文件: `doc/database/backup/ccdi_structure.sql`
|
|||
|
|
- 数据文件: `doc/database/backup/ccdi_data.sql`
|
|||
|
|
- 设计文档: `docs/plans/2026-02-28-database-migration-design.md`
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 2: 提交操作指南**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
git add doc/database/backup/export_guide.md
|
|||
|
|
git commit -m "docs: 添加数据库迁移操作指南"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 7: 完整验证流程
|
|||
|
|
|
|||
|
|
**Files:**
|
|||
|
|
- 无文件修改,仅验证操作
|
|||
|
|
|
|||
|
|
**Step 1: 验证脚本帮助信息**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
./export_database.sh help
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
预期输出:
|
|||
|
|
```
|
|||
|
|
用法: ./export_database.sh <command> [options]
|
|||
|
|
|
|||
|
|
命令:
|
|||
|
|
export 导出数据库
|
|||
|
|
import <env> 导入数据库到指定环境
|
|||
|
|
help 显示帮助信息
|
|||
|
|
|
|||
|
|
环境:
|
|||
|
|
production, prod 生产环境
|
|||
|
|
test 测试环境
|
|||
|
|
|
|||
|
|
示例:
|
|||
|
|
./export_database.sh export # 导出数据库到 doc/database/backup/ 目录
|
|||
|
|
./export_database.sh import test # 导入数据库到测试环境
|
|||
|
|
./export_database.sh import prod # 导入数据库到生产环境
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 2: 验证配置文件**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cat db_config.conf
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
确保包含所有必需配置项。
|
|||
|
|
|
|||
|
|
**Step 3: 验证导出文件**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 检查文件存在
|
|||
|
|
ls -lh doc/database/backup/ccdi_*.sql
|
|||
|
|
|
|||
|
|
# 检查文件内容
|
|||
|
|
head -30 doc/database/backup/ccdi_structure.sql
|
|||
|
|
head -30 doc/database/backup/ccdi_data.sql
|
|||
|
|
|
|||
|
|
# 统计表数量
|
|||
|
|
grep "CREATE TABLE" doc/database/backup/ccdi_structure.sql | wc -l
|
|||
|
|
|
|||
|
|
# 统计 INSERT 语句
|
|||
|
|
grep "INSERT INTO" doc/database/backup/ccdi_data.sql | wc -l
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 4: 创建验证报告**
|
|||
|
|
|
|||
|
|
创建临时验证报告:
|
|||
|
|
```bash
|
|||
|
|
cat > /tmp/migration_verify.txt << 'EOF'
|
|||
|
|
数据库迁移验证报告
|
|||
|
|
==================
|
|||
|
|
导出时间: $(date)
|
|||
|
|
|
|||
|
|
文件信息:
|
|||
|
|
- 表结构文件: $(ls -lh doc/database/backup/ccdi_structure.sql)
|
|||
|
|
- 数据文件: $(ls -lh doc/database/backup/ccdi_data.sql)
|
|||
|
|
|
|||
|
|
表数量: $(grep "CREATE TABLE" doc/database/backup/ccdi_structure.sql | wc -l)
|
|||
|
|
|
|||
|
|
字符集检查:
|
|||
|
|
$(grep "SET NAMES utf8mb4" doc/database/backup/ccdi_structure.sql)
|
|||
|
|
|
|||
|
|
验证结果: 通过
|
|||
|
|
EOF
|
|||
|
|
cat /tmp/migration_verify.txt
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 成功标准
|
|||
|
|
|
|||
|
|
完成后,应满足以下所有条件:
|
|||
|
|
|
|||
|
|
1. ✅ 配置文件模板 `db_config.conf.template` 已创建
|
|||
|
|
2. ✅ `db_config.conf` 已添加到 `.gitignore`
|
|||
|
|
3. ✅ 自动化脚本 `export_database.sh` 可执行
|
|||
|
|
4. ✅ 执行 `./export_database.sh export` 成功生成两个 SQL 文件
|
|||
|
|
5. ✅ `ccdi_structure.sql` 包含所有表结构和字符集声明
|
|||
|
|
6. ✅ `ccdi_data.sql` 包含所有数据和字符集声明
|
|||
|
|
7. ✅ SQL 文件无乱码,字符集正确
|
|||
|
|
8. ✅ 操作指南文档清晰完整
|
|||
|
|
9. ✅ 所有代码已提交到 Git
|
|||
|
|
|
|||
|
|
## 执行建议
|
|||
|
|
|
|||
|
|
**建议执行顺序**:
|
|||
|
|
1. 在测试环境完整执行一遍流程
|
|||
|
|
2. 验证测试环境导入的数据完整性
|
|||
|
|
3. 确认无问题后,在生产环境执行
|
|||
|
|
4. 验证生产环境数据完整性
|
|||
|
|
5. 应用程序连接测试
|
|||
|
|
|
|||
|
|
**时间估算**:
|
|||
|
|
- Task 1-3: 15分钟(脚本开发)
|
|||
|
|
- Task 4: 20-30分钟(导出执行,取决于数据量)
|
|||
|
|
- Task 5: 10分钟(添加导入功能)
|
|||
|
|
- Task 6-7: 15分钟(文档和验证)
|
|||
|
|
|
|||
|
|
**总计**: 约 60-70 分钟
|