数据迁移脚本#

脚本说明#

数据迁移脚本用于在不同数据库之间迁移数据,包括表结构迁移、数据迁移、索引迁移等。

脚本代码#

#!/bin/bash

# 数据迁移脚本
# 功能:在不同数据库之间迁移数据
# 作者:System Admin
# 日期:2024-01-01

set -euo pipefail

# 配置变量
LOG_FILE="/var/log/data_migration.log"
TEMP_DIR="/tmp/migration"
SOURCE_TYPE=""
SOURCE_HOST=""
SOURCE_PORT=""
SOURCE_USER=""
SOURCE_PASS=""
SOURCE_DB=""
TARGET_TYPE=""
TARGET_HOST=""
TARGET_PORT=""
TARGET_USER=""
TARGET_PASS=""
TARGET_DB=""
MIGRATE_SCHEMA=true
MIGRATE_DATA=true
MIGRATE_INDEX=true

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# 日志函数
log() {
    local level=$1
    shift
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$timestamp] [$level] $@" | tee -a "$LOG_FILE"
}

log_info() {
    log "INFO" "$@"
}

log_error() {
    log "ERROR" "$@"
}

# 创建临时目录
create_temp_dir() {
    if [ ! -d "$TEMP_DIR" ]; then
        mkdir -p "$TEMP_DIR"
        log_info "创建临时目录: $TEMP_DIR"
    fi
}

# 导出MySQL数据
export_mysql() {
    local host=$1
    local port=$2
    local user=$3
    local pass=$4
    local db=$5
    local output_dir=$6
    
    log_info "导出MySQL数据: $db"
    
    # 导出表结构
    if [ "$MIGRATE_SCHEMA" = true ]; then
        mysqldump -h "$host" -P "$port" -u "$user" -p"$pass" \
            --no-data --single-transaction "$db" > "$output_dir/schema.sql"
        log_info "表结构导出完成"
    fi
    
    # 导出数据
    if [ "$MIGRATE_DATA" = true ]; then
        mysqldump -h "$host" -P "$port" -u "$user" -p"$pass" \
            --no-create-info --single-transaction --quick "$db" > "$output_dir/data.sql"
        log_info "数据导出完成"
    fi
    
    # 导出索引
    if [ "$MIGRATE_INDEX" = true ]; then
        mysqldump -h "$host" -P "$port" -u "$user" -p"$pass" \
            --no-data --single-transaction "$db" > "$output_dir/index.sql"
        log_info "索引导出完成"
    fi
}

# 导出PostgreSQL数据
export_postgresql() {
    local host=$1
    local port=$2
    local user=$3
    local pass=$4
    local db=$5
    local output_dir=$6
    
    log_info "导出PostgreSQL数据: $db"
    
    # 导出表结构
    if [ "$MIGRATE_SCHEMA" = true ]; then
        pg_dump -h "$host" -p "$port" -U "$user" -d "$db" \
            --schema-only -f "$output_dir/schema.sql"
        log_info "表结构导出完成"
    fi
    
    # 导出数据
    if [ "$MIGRATE_DATA" = true ]; then
        pg_dump -h "$host" -p "$port" -U "$user" -d "$db" \
            --data-only -f "$output_dir/data.sql"
        log_info "数据导出完成"
    fi
    
    # 导出索引
    if [ "$MIGRATE_INDEX" = true ]; then
        pg_dump -h "$host" -p "$port" -U "$user" -d "$db" \
            --schema-only -f "$output_dir/index.sql"
        log_info "索引导出完成"
    fi
}

# 导出MongoDB数据
export_mongodb() {
    local host=$1
    local port=$2
    local user=$3
    local pass=$4
    local db=$5
    local output_dir=$6
    
    log_info "导出MongoDB数据: $db"
    
    # 导出数据
    mongodump -h "$host" --port "$port" -u "$user" -p "$pass" \
        -d "$db" -o "$output_dir"
    log_info "数据导出完成"
}

# 导入MySQL数据
import_mysql() {
    local host=$1
    local port=$2
    local user=$3
    local pass=$4
    local db=$5
    local input_dir=$6
    
    log_info "导入MySQL数据: $db"
    
    # 创建数据库
    mysql -h "$host" -P "$port" -u "$user" -p"$pass" \
        -e "CREATE DATABASE IF NOT EXISTS $db;"
    
    # 导入表结构
    if [ "$MIGRATE_SCHEMA" = true ] && [ -f "$input_dir/schema.sql" ]; then
        mysql -h "$host" -P "$port" -u "$user" -p"$pass" \
            "$db" < "$input_dir/schema.sql"
        log_info "表结构导入完成"
    fi
    
    # 导入数据
    if [ "$MIGRATE_DATA" = true ] && [ -f "$input_dir/data.sql" ]; then
        mysql -h "$host" -P "$port" -u "$user" -p"$pass" \
            "$db" < "$input_dir/data.sql"
        log_info "数据导入完成"
    fi
    
    # 导入索引
    if [ "$MIGRATE_INDEX" = true ] && [ -f "$input_dir/index.sql" ]; then
        mysql -h "$host" -P "$port" -u "$user" -p"$pass" \
            "$db" < "$input_dir/index.sql"
        log_info "索引导入完成"
    fi
}

# 导入PostgreSQL数据
import_postgresql() {
    local host=$1
    local port=$2
    local user=$3
    local pass=$4
    local db=$5
    local input_dir=$6
    
    log_info "导入PostgreSQL数据: $db"
    
    # 创建数据库
    psql -h "$host" -p "$port" -U "$user" \
        -c "CREATE DATABASE $db;"
    
    # 导入表结构
    if [ "$MIGRATE_SCHEMA" = true ] && [ -f "$input_dir/schema.sql" ]; then
        psql -h "$host" -p "$port" -U "$user" -d "$db" \
            -f "$input_dir/schema.sql"
        log_info "表结构导入完成"
    fi
    
    # 导入数据
    if [ "$MIGRATE_DATA" = true ] && [ -f "$input_dir/data.sql" ]; then
        psql -h "$host" -p "$port" -U "$user" -d "$db" \
            -f "$input_dir/data.sql"
        log_info "数据导入完成"
    fi
    
    # 导入索引
    if [ "$MIGRATE_INDEX" = true ] && [ -f "$input_dir/index.sql" ]; then
        psql -h "$host" -p "$port" -U "$user" -d "$db" \
            -f "$input_dir/index.sql"
        log_info "索引导入完成"
    fi
}

# 导入MongoDB数据
import_mongodb() {
    local host=$1
    local port=$2
    local user=$3
    local pass=$4
    local db=$5
    local input_dir=$6
    
    log_info "导入MongoDB数据: $db"
    
    # 导入数据
    mongorestore -h "$host" --port "$port" -u "$user" -p "$pass" \
        -d "$db" "$input_dir/$db"
    log_info "数据导入完成"
}

# MySQL到MySQL迁移
mysql_to_mysql() {
    log_info "MySQL到MySQL迁移"
    
    local output_dir="$TEMP_DIR/mysql_export"
    mkdir -p "$output_dir"
    
    # 导出数据
    export_mysql "$SOURCE_HOST" "$SOURCE_PORT" "$SOURCE_USER" "$SOURCE_PASS" \
        "$SOURCE_DB" "$output_dir"
    
    # 导入数据
    import_mysql "$TARGET_HOST" "$TARGET_PORT" "$TARGET_USER" "$TARGET_PASS" \
        "$TARGET_DB" "$output_dir"
    
    log_info "MySQL到MySQL迁移完成"
}

# MySQL到PostgreSQL迁移
mysql_to_postgresql() {
    log_info "MySQL到PostgreSQL迁移"
    
    local output_dir="$TEMP_DIR/mysql_export"
    mkdir -p "$output_dir"
    
    # 导出数据
    export_mysql "$SOURCE_HOST" "$SOURCE_PORT" "$SOURCE_USER" "$SOURCE_PASS" \
        "$SOURCE_DB" "$output_dir"
    
    # 转换数据类型
    # 这里可以添加数据类型转换逻辑
    
    # 导入数据
    import_postgresql "$TARGET_HOST" "$TARGET_PORT" "$TARGET_USER" "$TARGET_PASS" \
        "$TARGET_DB" "$output_dir"
    
    log_info "MySQL到PostgreSQL迁移完成"
}

# PostgreSQL到MySQL迁移
postgresql_to_mysql() {
    log_info "PostgreSQL到MySQL迁移"
    
    local output_dir="$TEMP_DIR/postgresql_export"
    mkdir -p "$output_dir"
    
    # 导出数据
    export_postgresql "$SOURCE_HOST" "$SOURCE_PORT" "$SOURCE_USER" "$SOURCE_PASS" \
        "$SOURCE_DB" "$output_dir"
    
    # 转换数据类型
    # 这里可以添加数据类型转换逻辑
    
    # 导入数据
    import_mysql "$TARGET_HOST" "$TARGET_PORT" "$TARGET_USER" "$TARGET_PASS" \
        "$TARGET_DB" "$output_dir"
    
    log_info "PostgreSQL到MySQL迁移完成"
}

# PostgreSQL到PostgreSQL迁移
postgresql_to_postgresql() {
    log_info "PostgreSQL到PostgreSQL迁移"
    
    local output_dir="$TEMP_DIR/postgresql_export"
    mkdir -p "$output_dir"
    
    # 导出数据
    export_postgresql "$SOURCE_HOST" "$SOURCE_PORT" "$SOURCE_USER" "$SOURCE_PASS" \
        "$SOURCE_DB" "$output_dir"
    
    # 导入数据
    import_postgresql "$TARGET_HOST" "$TARGET_PORT" "$TARGET_USER" "$TARGET_PASS" \
        "$TARGET_DB" "$output_dir"
    
    log_info "PostgreSQL到PostgreSQL迁移完成"
}

# MongoDB到MongoDB迁移
mongodb_to_mongodb() {
    log_info "MongoDB到MongoDB迁移"
    
    local output_dir="$TEMP_DIR/mongodb_export"
    mkdir -p "$output_dir"
    
    # 导出数据
    export_mongodb "$SOURCE_HOST" "$SOURCE_PORT" "$SOURCE_USER" "$SOURCE_PASS" \
        "$SOURCE_DB" "$output_dir"
    
    # 导入数据
    import_mongodb "$TARGET_HOST" "$TARGET_PORT" "$TARGET_USER" "$TARGET_PASS" \
        "$TARGET_DB" "$output_dir"
    
    log_info "MongoDB到MongoDB迁移完成"
}

# 验证迁移
verify_migration() {
    log_info "验证迁移结果"
    
    # 比较表数量
    local source_tables
    local target_tables
    
    case $SOURCE_TYPE in
        mysql)
            source_tables=$(mysql -h "$SOURCE_HOST" -P "$SOURCE_PORT" -u "$SOURCE_USER" -p"$SOURCE_PASS" \
                "$SOURCE_DB" -e "SHOW TABLES;" | wc -l)
            ;;
        postgresql)
            source_tables=$(psql -h "$SOURCE_HOST" -p "$SOURCE_PORT" -U "$SOURCE_USER" -d "$SOURCE_DB" \
                -c "\dt" | wc -l)
            ;;
        mongodb)
            source_tables=$(mongo --host "$SOURCE_HOST" --port "$SOURCE_PORT" -u "$SOURCE_USER" -p "$SOURCE_PASS" \
                "$SOURCE_DB" --eval "db.getCollectionNames().length" --quiet)
            ;;
    esac
    
    case $TARGET_TYPE in
        mysql)
            target_tables=$(mysql -h "$TARGET_HOST" -P "$TARGET_PORT" -u "$TARGET_USER" -p"$TARGET_PASS" \
                "$TARGET_DB" -e "SHOW TABLES;" | wc -l)
            ;;
        postgresql)
            target_tables=$(psql -h "$TARGET_HOST" -p "$TARGET_PORT" -U "$TARGET_USER" -d "$TARGET_DB" \
                -c "\dt" | wc -l)
            ;;
        mongodb)
            target_tables=$(mongo --host "$TARGET_HOST" --port "$TARGET_PORT" -u "$TARGET_USER" -p "$TARGET_PASS" \
                "$TARGET_DB" --eval "db.getCollectionNames().length" --quiet)
            ;;
    esac
    
    echo "源数据库表数量: $source_tables"
    echo "目标数据库表数量: $target_tables"
    
    if [ "$source_tables" = "$target_tables" ]; then
        log_info "迁移验证通过"
        return 0
    else
        log_error "迁移验证失败:表数量不匹配"
        return 1
    fi
}

# 清理临时文件
cleanup_temp_files() {
    log_info "清理临时文件"
    
    rm -rf "$TEMP_DIR"
    
    log_info "临时文件清理完成"
}

# 显示帮助
show_help() {
    echo "用法: $0 [选项]"
    echo ""
    echo "选项:"
    echo "  --source-type <类型>     源数据库类型(mysql/postgresql/mongodb)"
    echo "  --source-host <主机>     源数据库主机"
    echo "  --source-port <端口>     源数据库端口"
    echo "  --source-user <用户>     源数据库用户"
    echo "  --source-pass <密码>     源数据库密码"
    echo "  --source-db <数据库>     源数据库名"
    echo "  --target-type <类型>     目标数据库类型(mysql/postgresql/mongodb)"
    echo "  --target-host <主机>     目标数据库主机"
    echo "  --target-port <端口>     目标数据库端口"
    echo "  --target-user <用户>     目标数据库用户"
    echo "  --target-pass <密码>     目标数据库密码"
    echo "  --target-db <数据库>     目标数据库名"
    echo "  --no-schema              不迁移表结构"
    echo "  --no-data                不迁移数据"
    echo "  --no-index               不迁移索引"
    echo "  --verify                 验证迁移结果"
    echo "  --cleanup                清理临时文件"
    echo "  -h                       显示帮助信息"
    echo ""
    echo "示例:"
    echo "  $0 --source-type mysql --source-host localhost --source-user root --source-pass password --source-db mydb \\"
    echo "     --target-type postgresql --target-host localhost --target-user postgres --target-db newdb --verify"
}

# 主函数
main() {
    # 解析选项
    while [ $# -gt 0 ]; do
        case $1 in
            --source-type)
                SOURCE_TYPE="$2"
                shift 2
                ;;
            --source-host)
                SOURCE_HOST="$2"
                shift 2
                ;;
            --source-port)
                SOURCE_PORT="$2"
                shift 2
                ;;
            --source-user)
                SOURCE_USER="$2"
                shift 2
                ;;
            --source-pass)
                SOURCE_PASS="$2"
                shift 2
                ;;
            --source-db)
                SOURCE_DB="$2"
                shift 2
                ;;
            --target-type)
                TARGET_TYPE="$2"
                shift 2
                ;;
            --target-host)
                TARGET_HOST="$2"
                shift 2
                ;;
            --target-port)
                TARGET_PORT="$2"
                shift 2
                ;;
            --target-user)
                TARGET_USER="$2"
                shift 2
                ;;
            --target-pass)
                TARGET_PASS="$2"
                shift 2
                ;;
            --target-db)
                TARGET_DB="$2"
                shift 2
                ;;
            --no-schema)
                MIGRATE_SCHEMA=false
                shift
                ;;
            --no-data)
                MIGRATE_DATA=false
                shift
                ;;
            --no-index)
                MIGRATE_INDEX=false
                shift
                ;;
            --verify)
                VERIFY=true
                shift
                ;;
            --cleanup)
                cleanup_temp_files
                exit 0
                ;;
            -h)
                show_help
                exit 0
                ;;
            *)
                log_error "无效选项: $1"
                show_help
                exit 1
                ;;
        esac
    done
    
    # 创建临时目录
    create_temp_dir
    
    # 执行迁移
    case "${SOURCE_TYPE}_${TARGET_TYPE}" in
        mysql_mysql)
            mysql_to_mysql
            ;;
        mysql_postgresql)
            mysql_to_postgresql
            ;;
        postgresql_mysql)
            postgresql_to_mysql
            ;;
        postgresql_postgresql)
            postgresql_to_postgresql
            ;;
        mongodb_mongodb)
            mongodb_to_mongodb
            ;;
        *)
            log_error "不支持的迁移类型: ${SOURCE_TYPE} -> ${TARGET_TYPE}"
            exit 1
            ;;
    esac
    
    # 验证迁移
    if [ "${VERIFY:-false}" = true ]; then
        verify_migration
    fi
    
    log_info "数据迁移完成"
}

# 执行主函数
main "$@"

使用说明#

  1. 添加执行权限:

    chmod +x data_migration.sh
  2. 基本用法:

    # MySQL到MySQL迁移
    ./data_migration.sh --source-type mysql --source-host localhost --source-user root --source-pass password --source-db mydb \
        --target-type mysql --target-host remotehost --target-user root --target-pass password --target-db newdb
    
    # MySQL到PostgreSQL迁移
    ./data_migration.sh --source-type mysql --source-host localhost --source-user root --source-pass password --source-db mydb \
        --target-type postgresql --target-host localhost --target-user postgres --target-db newdb
  3. 高级用法:

    # 只迁移表结构
    ./data_migration.sh --source-type mysql --source-host localhost --source-user root --source-pass password --source-db mydb \
        --target-type postgresql --target-host localhost --target-user postgres --target-db newdb --no-data --no-index
    
    # 验证迁移结果
    ./data_migration.sh --source-type mysql --source-host localhost --source-user root --source-pass password --source-db mydb \
        --target-type postgresql --target-host localhost --target-user postgres --target-db newdb --verify
    
    # 清理临时文件
    ./data_migration.sh --cleanup

功能特点#

  • 多数据库支持(MySQL、PostgreSQL、MongoDB)
  • 表结构迁移
  • 数据迁移
  • 索引迁移
  • 迁移验证
  • 临时文件管理

依赖项#

  • mysqldump/mysql: MySQL工具
  • pg_dump/psql: PostgreSQL工具
  • mongodump/mongorestore: MongoDB工具

注意事项#

  1. 需要数据库用户有足够权限
  2. 不同数据库之间迁移需要数据类型转换
  3. 大数据量迁移可能需要较长时间
  4. 建议先备份目标数据库
  5. 验证功能可以确保迁移完整性