MySQL数据库迁移脚本及使用说明

脚本源码

bash 复制代码
#!/bin/bash

# 数据库迁移脚本 - 导出MySQL数据库并导入到新机器
# 支持可配置的数据库列表和目标服务器IP地址

# 默认配置
SOURCE_HOST="127.0.0.1"
SOURCE_USER="user"
SOURCE_PASS="password"
TARGET_HOST="127.0.0.1"
TARGET_USER="user"
TARGET_PASS="password"
DB_LIST=("net" "event" "scd" "stgy" "web")
BACKUP_DIR="/tmp/mysql_backup_$(date +%Y%m%d_%H%M%S)"
COMPRESS=true

# 帮助信息
show_help() {
    echo "用法: $0 [选项]"
    echo "选项:"
    echo "  -s, --source-host  源数据库主机地址 (默认: $SOURCE_HOST)"
    echo "  -u, --source-user  源数据库用户名 (默认: $SOURCE_USER)"
    echo "  -p, --source-pass  源数据库密码"
    echo "  -t, --target-host  目标数据库主机地址 (默认: $TARGET_HOST)"
    echo "  -U, --target-user  目标数据库用户名 (默认: $TARGET_USER)"
    echo "  -P, --target-pass  目标数据库密码"
    echo "  -d, --databases    要迁移的数据库列表,用逗号分隔 (默认: net,event,scd,stgyweb)"
    echo "  -o, --output-dir   备份目录 (默认: /tmp/mysql_backup_时间戳)"
    echo "  -c, --compress     是否压缩备份文件 (true/false,默认: true)"
    echo "  -h, --help         显示此帮助信息"
    echo "  --export-only      仅导出数据库,不导入"
    echo "  --import-only      仅导入数据库(需指定备份目录)"
    echo ""
    echo "示例:"
    echo "  # 使用默认配置导出导入所有数据库到本地"
    echo "  $0"
    echo ""
    echo "  # 导出到指定IP的服务器"
    echo "  $0 --target-host 192.168.1.100 --target-user admin --target-pass password"
    echo ""
    echo "  # 仅导出特定数据库"
    echo "  $0 --databases net,event --export-only"
    echo ""
    echo "  # 仅导入特定备份目录"
    echo "  $0 --import-only --output-dir /tmp/mysql_backup_20230101_120000"
}

# 解析命令行参数
while [[ $# -gt 0 ]]; do
    case $1 in
        -s|--source-host)
            SOURCE_HOST="$2"
            shift 2
            ;;
        -u|--source-user)
            SOURCE_USER="$2"
            shift 2
            ;;
        -p|--source-pass)
            SOURCE_PASS="$2"
            shift 2
            ;;
        -t|--target-host)
            TARGET_HOST="$2"
            shift 2
            ;;
        -U|--target-user)
            TARGET_USER="$2"
            shift 2
            ;;
        -P|--target-pass)
            TARGET_PASS="$2"
            shift 2
            ;;
        -d|--databases)
            IFS=',' read -r -a DB_LIST <<< "$2"
            shift 2
            ;;
        -o|--output-dir)
            BACKUP_DIR="$2"
            shift 2
            ;;
        -c|--compress)
            COMPRESS="$2"
            shift 2
            ;;
        -h|--help)
            show_help
            exit 0
            ;;
        --export-only)
            EXPORT_ONLY=true
            shift
            ;;
        --import-only)
            IMPORT_ONLY=true
            shift
            ;;
        *)
            echo "未知选项: $1"
            show_help
            exit 1
            ;;
    esac
done

# 检查必要的工具
check_requirements() {
    if ! command -v mysqldump &> /dev/null; then
        echo "错误: 未找到 mysqldump 命令,请安装 MySQL 客户端工具。"
        exit 1
    fi
    
    if ! command -v mysql &> /dev/null; then
        echo "错误: 未找到 mysql 命令,请安装 MySQL 客户端工具。"
        exit 1
    fi
    
    if [ "$COMPRESS" = true ] && ! command -v gzip &> /dev/null; then
        echo "警告: 未找到 gzip 命令,将不压缩备份文件。"
        COMPRESS=false
    fi
}

# 导出数据库
export_databases() {
    echo "开始导出数据库..."
    echo "源数据库主机: $SOURCE_HOST"
    echo "数据库列表: ${DB_LIST[*]}"
    echo "备份目录: $BACKUP_DIR"
    
    # 创建备份目录
    mkdir -p "$BACKUP_DIR"
    
    # 导出每个数据库
    for db in "${DB_LIST[@]}"; do
        echo "正在导出数据库: $db"
        
        # 构建导出命令
        EXPORT_CMD="mysqldump -h $SOURCE_HOST -u $SOURCE_USER"
        if [ -n "$SOURCE_PASS" ]; then
            EXPORT_CMD="$EXPORT_CMD -p$SOURCE_PASS"
        fi
        
        # 添加--databases选项来包含创建数据库的语句
        EXPORT_CMD="$EXPORT_CMD --databases $db"
        
        # 添加一些常用的选项
        EXPORT_CMD="$EXPORT_CMD --single-transaction --routines --triggers --events"
        
        # 根据是否压缩构建完整命令
        if [ "$COMPRESS" = true ]; then
            EXPORT_CMD="$EXPORT_CMD | gzip > $BACKUP_DIR/${db}.sql.gz"
            echo "执行: $EXPORT_CMD"
            eval "$EXPORT_CMD"
        else
            EXPORT_CMD="$EXPORT_CMD > $BACKUP_DIR/${db}.sql"
            echo "执行: $EXPORT_CMD"
            eval "$EXPORT_CMD"
        fi
        
        # 检查导出是否成功
        if [ $? -eq 0 ]; then
            echo "数据库 $db 导出成功。"
        else
            echo "错误: 数据库 $db 导出失败!"
            export_errors=true
        fi
    done
    
    # 生成配置文件记录导出信息
    cat > "$BACKUP_DIR/backup_info.txt" << EOF
备份时间: $(date '+%Y-%m-%d %H:%M:%S')
源数据库主机: $SOURCE_HOST
源数据库用户名: $SOURCE_USER
数据库列表: ${DB_LIST[*]}
是否压缩: $COMPRESS
EOF
    
    if [ -n "$export_errors" ]; then
        echo "警告: 部分数据库导出失败!"
        return 1
    else
        echo "所有数据库导出成功!"
        return 0
    fi
}

# 导入数据库
import_databases() {
    echo "开始导入数据库..."
    echo "目标数据库主机: $TARGET_HOST"
    echo "备份目录: $BACKUP_DIR"
    
    # 检查备份目录是否存在
    if [ ! -d "$BACKUP_DIR" ]; then
        echo "错误: 备份目录 '$BACKUP_DIR' 不存在!"
        exit 1
    fi
    
    # 检查备份信息文件
    if [ -f "$BACKUP_DIR/backup_info.txt" ]; then
        echo "备份信息:"
        cat "$BACKUP_DIR/backup_info.txt"
    else
        echo "警告: 未找到备份信息文件。"
    fi
    
    # 确定要导入的文件列表
    if [ ${#DB_LIST[@]} -eq 0 ]; then
        # 如果没有指定数据库列表,尝试从备份目录中读取
        if [ "$COMPRESS" = true ] || ls "$BACKUP_DIR"/*.sql.gz 1> /dev/null 2>&1; then
            BACKUP_FILES=("$BACKUP_DIR"/*.sql.gz)
        else
            BACKUP_FILES=("$BACKUP_DIR"/*.sql)
        fi
    else
        # 如果指定了数据库列表,使用指定的列表
        BACKUP_FILES=()
        for db in "${DB_LIST[@]}"; do
            if [ -f "$BACKUP_DIR/${db}.sql.gz" ]; then
                BACKUP_FILES+=("$BACKUP_DIR/${db}.sql.gz")
                COMPRESS=true
            elif [ -f "$BACKUP_DIR/${db}.sql" ]; then
                BACKUP_FILES+=("$BACKUP_DIR/${db}.sql")
            else
                echo "警告: 未找到数据库 $db 的备份文件!"
            fi
        done
    fi
    
    # 导入每个数据库文件
    import_errors=false
    for file in "${BACKUP_FILES[@]}"; do
        # 提取数据库名
        db_name=$(basename "$file")
        db_name=${db_name%.sql.gz}
        db_name=${db_name%.sql}
        
        echo "正在导入数据库: $db_name"
        
        # 构建导入命令
        IMPORT_CMD="mysql -h $TARGET_HOST -u $TARGET_USER"
        if [ -n "$TARGET_PASS" ]; then
            IMPORT_CMD="$IMPORT_CMD -p$TARGET_PASS"
        fi
        
        # 根据文件类型构建完整命令
        if [[ "$file" == *.gz ]]; then
            IMPORT_CMD="gzip -dc $file | $IMPORT_CMD"
            echo "执行: $IMPORT_CMD"
            eval "$IMPORT_CMD"
        else
            IMPORT_CMD="$IMPORT_CMD < $file"
            echo "执行: $IMPORT_CMD"
            eval "$IMPORT_CMD"
        fi
        
        # 检查导入是否成功
        if [ $? -eq 0 ]; then
            echo "数据库 $db_name 导入成功。"
        else
            echo "错误: 数据库 $db_name 导入失败!"
            import_errors=true
        fi
    done
    
    if [ -n "$import_errors" ]; then
        echo "警告: 部分数据库导入失败!"
        return 1
    else
        echo "所有数据库导入成功!"
        return 0
    fi
}

# 主函数
main() {
    echo "========================================"
    echo "MySQL数据库迁移工具"
    echo "========================================"
    
    # 检查必要的工具
    check_requirements
    
    # 根据参数执行导出或导入
    if [ "$IMPORT_ONLY" != true ]; then
        export_databases
        export_result=$?
    fi
    
    if [ "$EXPORT_ONLY" != true ] && [ "$IMPORT_ONLY" != true ]; then
        # 如果不是仅导出或仅导入,则在导出后进行导入
        if [ $export_result -eq 0 ]; then
            import_databases
        else
            echo "由于导出失败,跳过导入步骤。"
            exit 1
        fi
    elif [ "$IMPORT_ONLY" == true ]; then
        # 如果是仅导入,则直接执行导入
        import_databases
    fi
    
    echo "========================================"
    echo "迁移完成!"
    echo "========================================"
}

# 执行主函数
main

脚本概述

这是一个功能完整的MySQL数据库迁移工具,支持将多个数据库从源服务器导出并导入到目标服务器。脚本使用mysqldump进行逻辑备份,确保数据迁移的兼容性和可靠性。

主要特性:

  • 支持批量迁移多个数据库
  • 可配置的源和目标服务器连接参数
  • 可选择压缩备份以节省磁盘空间
  • 支持导出/导入分离操作
  • 完整的错误检查和日志记录

快速开始

基本用法

bash 复制代码
# 使用默认配置迁移所有数据库到本地
./mysql_migration.sh

# 迁移到远程服务器
./mysql_migration.sh --target-host 192.168.1.100 --target-user admin --target-pass password

# 仅迁移特定数据库
./mysql_migration.sh --databases net,event

常见用法

从本机迁移数据库到指定主机
  1. 将所有数据库迁移到指定主机

    bash 复制代码
    ./db_migrate.sh --source-host 127.0.0.1 --target-host 10.10.110.46
  2. 仅迁移某个数据库到指定主机

    bash 复制代码
    ./db_migrate.sh --source-host 127.0.0.1 --target-host 10.10.110.46 -d scd
将其他主机数据库迁移到指定主机
  1. 将所有数据库迁移到指定主机

    bash 复制代码
    ./db_migrate.sh --source-host 10.10.112.3 --target-host 10.10.110.46
  2. 仅迁移某个数据库到指定主机

    bash 复制代码
    ./db_migrate.sh --source-host 10.10.112.3 --target-host 10.10.110.46 -d web 

参数详解

连接参数

参数 简写 默认值 说明
--source-host -s 127.0.0.1 源数据库主机地址
--source-user -u username 源数据库用户名
--source-pass -p password 源数据库密码
--target-host -t 127.0.0.1 目标数据库主机地址
--target-user -U username 目标数据库用户名
--target-pass -P password 目标数据库密码

功能参数

参数 简写 默认值 说明
--databases -d net,event,scd,stgy,web 要迁移的数据库列表(逗号分隔)
--output-dir -o 自动生成 备份文件存储目录
--compress -c true 是否压缩备份文件
--export-only false 仅执行导出操作
--import-only false 仅执行导入操作(需指定备份目录)

使用示例

完整迁移到远程服务器

bash 复制代码
 ./mysql_migration.sh \
   --source-host 192.168.1.50 \
   --source-user dbadmin \
   --source-pass src_password \
   --target-host 192.168.1.100 \
   --target-user dbadmin \
   --target-pass tgt_password \
   --databases net,event,scd

分步执行

bash 复制代码
 # 第一步:仅导出数据库
 ./mysql_migration.sh \
   --source-host 192.168.1.50 \
   --export-only \
   --output-dir /backup/mysql_20231213

 # 第二步:将备份文件传输到目标服务器
 scp -r /backup/mysql_20231213 user@target-server:/tmp/

 # 第三步:在目标服务器上导入
 ./mysql_migration.sh \
   --target-host 192.168.1.100 \
   --import-only \
   --output-dir /tmp/mysql_20231213

大型数据库优化

对于大型数据库,建议添加性能优化参数:

bash 复制代码
 # 在脚本中的EXPORT_CMD变量添加以下参数:
 EXPORT_CMD="$EXPORT_CMD --single-transaction --quick --skip-lock-tables"

迁移技术细节

导出参数说明

脚本使用的关键mysqldump参数:

  • --single-transaction:在事务中执行导出,确保数据一致性
  • --routines:导出存储过程和函数
  • --triggers:导出触发器
  • --events:导出事件调度器
  • --databases:包含创建数据库语句

备份文件结构

复制代码
/tmp/mysql_backup_20231213_143022/
├── net.sql.gz          # 压缩的数据库备份
├── event.sql.gz
├── scd.sql.gz
├── stgy.sql.gz
├── web.sql.gz
└── backup_info.txt     # 备份元数据信息

最佳实践建议

1. 迁移前准备

权限检查:确保数据库用户有足够权限

复制代码
-- 源数据库用户需要SELECT、LOCK TABLES权限
GRANT SELECT, LOCK TABLES ON source_db.* TO 'username'@'localhost';

-- 目标数据库用户需要CREATE、INSERT等权限
GRANT CREATE, INSERT, UPDATE ON target_db.* TO 'username'@'localhost';

版本兼容性:检查MySQL版本兼容性,特别是5.7到8.0的迁移

2. 大数据量迁移优化

分批次迁移:对于特大表可以考虑分批次导出

bash 复制代码
 # 按条件分批导出大数据表
 mysqldump --where="id BETWEEN 1 AND 1000000" large_table > part1.sql

网络优化:使用压缩传输减少网络带宽占用

bash 复制代码
# 管道直接传输(避免中间文件)
mysqldump -h source_host -u user -p db | gzip | ssh user@target_host "gunzip | mysql -u user -p db"

3. 数据一致性验证

迁移完成后建议进行数据验证:

bash 复制代码
 # 记录数对比
 source_count=$(mysql -h source_host -u user -p -N -s -e "SELECT COUNT(*) FROM table")
 target_count=$(mysql -h target_host -u user -p -N -s -e "SELECT COUNT(*) FROM table")
 echo "Source: $source_count | Target: $target_count"

故障排除

常见问题解决

  1. 连接失败

    • 检查防火墙设置和端口访问(默认3306)
    • 验证用户名和密码是否正确
    • 确认MySQL服务是否正常运行
  2. 权限错误

    • 确保用户有导出/导入权限
    • 检查数据库名是否正确
  3. 字符集问题

    • 添加字符集参数:--default-character-set=utf8mb4
    • 统一源和目标数据库的字符集设置
  4. 大数据量导出超时

    • 调整超时参数:SET GLOBAL ob_query_timeout=1000000000;
    • 使用--quick参数优化大表导出

注意事项

  1. 业务影响:迁移期间建议停止使用源数据库的应用程序
  2. 存储空间:确保备份目录有足够磁盘空间
  3. 网络稳定性:跨网络迁移需要稳定的网络连接
  4. 回滚方案:重要数据迁移前建议做好备份
  5. 触发器处理:注意触发器的导出和导入设置

扩展功能

如需更高级的数据库版本控制,可以考虑集成Flyway或Liquibase等专业工具,它们提供更好的版本管理和回滚能力。

此脚本提供了MySQL数据库迁移的基础功能,适用于大多数迁移场景。根据具体需求可以进一步定制和优化参数设置。

相关推荐
soft20015256 小时前
《Rocky Linux 9.6 部署 MySQL 8.0 生产手册(含错误处理)》
linux·mysql·adb
帝吃藕和6 小时前
MySQL 知识点复习- 6. inner/right/left join
mysql
愚公移码6 小时前
蓝凌EKP产品:Hibernate 中 SessionFactory、Session 与事务的关系
java·数据库·hibernate·蓝凌
透明的玻璃杯6 小时前
sqlite数据库连接池
jvm·数据库·sqlite
VX:Fegn08956 小时前
计算机毕业设计|基于springboot + vue非遗传承文化管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
bleach-6 小时前
buuctf系列解题思路祥讲--[极客大挑战 2019]HardSQL1——sql报错注入
数据库·sql·安全·web安全·网络安全
少年攻城狮6 小时前
OceanBase系列---【oracle模式的存在即更新,不存在即新增的merge into用法】
数据库·oracle·oceanbase
你真的可爱呀7 小时前
3.MySQL 数据库集成
mysql·node.js·express
波波仔867 小时前
clickhouse简介
数据库·clickhouse