数据迁移脚本#
脚本说明#
数据迁移脚本用于在不同数据库之间迁移数据,包括表结构迁移、数据迁移、索引迁移等。
脚本代码#
#!/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 "$@"使用说明#
添加执行权限:
chmod +x data_migration.sh基本用法:
# 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高级用法:
# 只迁移表结构 ./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工具
注意事项#
- 需要数据库用户有足够权限
- 不同数据库之间迁移需要数据类型转换
- 大数据量迁移可能需要较长时间
- 建议先备份目标数据库
- 验证功能可以确保迁移完整性