Mysql 数据库迁移

一、数据库全量备份

bash 复制代码
#!/bin/bash

# 配置参数
DB_HOST="数据库IP地址"
DB_USER="数据库用户名"
DB_PASS="数据库密码"
BACKUP_DIR="/usr/local/mysqldump"
DATE=$(date +"%Y%m%d_%H%M%S")
LOG_FILE="$BACKUP_DIR/backup_$DATE.log"

# 创建备份目录
mkdir -p $BACKUP_DIR/$DATE

# 开始日志
echo "$(date): 开始MySQL全库备份" | tee -a $LOG_FILE

# 获取数据库列表(排除系统库)
echo "$(date): 获取数据库列表..." | tee -a $LOG_FILE
DATABASES=$(mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -e "SHOW DATABASES;" 2>/dev/null | grep -Ev "(Database|information_schema|performance_schema|sys)")

if [ $? -ne 0 ]; then
    echo "$(date): 错误:无法连接MySQL服务器" | tee -a $LOG_FILE
    exit 1
fi

echo "找到数据库: $DATABASES" | tee -a $LOG_FILE

# 备份每个数据库
for DB in $DATABASES; do
    echo "$(date): 备份数据库: $DB" | tee -a $LOG_FILE
    
    # 备份命令
    mysqldump -h $DB_HOST -u $DB_USER -p$DB_PASS \
              --single-transaction \
              --routines \
              --events \
              --triggers \
              --add-drop-database \
              $DB 2>> $LOG_FILE | gzip > $BACKUP_DIR/$DATE/${DB}_${DATE}.sql.gz
    
    # 检查备份是否成功
    if [ ${PIPESTATUS[0]} -eq 0 ]; then
        echo "$(date): ✓ 成功备份: $DB" | tee -a $LOG_FILE
    else
        echo "$(date): ✗ 备份失败: $DB" | tee -a $LOG_FILE
    fi
done

echo "$(date): 备份完成!文件保存在: $BACKUP_DIR/$DATE/" | tee -a $LOG_FILE

# 显示备份文件信息
echo "备份文件列表:" | tee -a $LOG_FILE
ls -lh $BACKUP_DIR/$DATE/ | tee -a $LOG_FILE

二、数据库备份恢复

bash 复制代码
#!/bin/bash

# 配置参数
NEW_DB_HOST="数据库IP地址"
NEW_DB_USER="数据库用户名"
NEW_DB_PASS="数据库密码"
# 数据库端口,默认3306
NEW_DB_PORT="3306"
BACKUP_DIR="数据库备份地址"

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

# 日志文件
LOG_FILE="$BACKUP_DIR/import_$(date +%Y%m%d_%H%M%S).log"

# 显示带颜色的消息
log_info() { echo -e "${GREEN}[INFO]${NC} $(date): $1" | tee -a $LOG_FILE; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $(date): $1" | tee -a $LOG_FILE; }
log_error() { echo -e "${RED}[ERROR]${NC} $(date): $1" | tee -a $LOG_FILE; }

# 测试数据库连接
test_db_connection() {
    log_info "测试数据库连接..."
    mysql -h $NEW_DB_HOST -P $NEW_DB_PORT -u $NEW_DB_USER -p$NEW_DB_PASS -e "SELECT 1;" > /dev/null 2>&1
    if [ $? -ne 0 ]; then
        log_error "无法连接到目标MySQL服务器"
        exit 1
    fi
    log_info "数据库连接测试成功"
}

# 获取备份文件列表
get_backup_files() {
    find $BACKUP_DIR -name "*.sql.gz" -type f | sort
}

# 从文件名提取数据库名
extract_db_name() {
    local filename=$(basename "$1") 
    # 使用sed去掉日期时间部分和扩展名
    echo "$filename" | sed 's/_[0-9]\{8\}_[0-9]\{6\}\.sql\.gz$//'
    #echo $filename | cut -d'_' -f1
}

# 创建数据库
create_database() {
    local db_name=$1
    log_info "创建数据库: $db_name"
    
    mysql -h $NEW_DB_HOST -P $NEW_DB_PORT -u $NEW_DB_USER -p$NEW_DB_PASS \
          -e "CREATE DATABASE IF NOT EXISTS \`$db_name\` 
              CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" 2>> $LOG_FILE
    
    if [ $? -eq 0 ]; then
        log_info "✓ 数据库创建成功: $db_name"
        return 0
    else
        log_error "创建数据库失败: $db_name"
        return 1
    fi
}

# 导入数据库
import_database() {
    local db_name=$1
    local backup_file=$2
    
    log_info "开始导入: $db_name"
    
    # 显示进度(估算)
    total_size=$(gunzip -c "$backup_file" | wc -c 2>/dev/null)
    if [ -n "$total_size" ]; then
        log_info "预计导入数据量: $(($total_size/1024/1024)) MB"
    fi
    
    # 导入数据
    start_time=$(date +%s)
    gunzip -c "$backup_file" | mysql -h $NEW_DB_HOST -P $NEW_DB_PORT -u $NEW_DB_USER -p$NEW_DB_PASS $db_name 2>> $LOG_FILE
    
    local import_status=$?
    end_time=$(date +%s)
    duration=$((end_time - start_time))
    
    if [ $import_status -eq 0 ]; then
        log_info "✓ 导入成功: $db_name (耗时: ${duration}秒)"
        return 0
    else
        log_error "导入失败: $db_name"
        return 1
    fi
}

# 主函数
main() {
    log_info "开始数据库导入过程"
    
    # 测试连接
    test_db_connection
    
    # 获取备份文件列表
    backup_files=$(get_backup_files)
    total_files=$(echo "$backup_files" | wc -l)
    current_file=0
    
    log_info "找到 $total_files 个备份文件需要导入"
    
    # 导入每个数据库
    success_count=0
    fail_count=0
    
    for backup_file in $backup_files; do
        current_file=$((current_file + 1))
        db_name=$(extract_db_name "$backup_file")
        
        log_info "处理文件 [$current_file/$total_files]: $db_name"
        
        # 创建数据库
        if create_database "$db_name"; then
            # 导入数据
            if import_database "$db_name" "$backup_file"; then
                success_count=$((success_count + 1))
            else
                fail_count=$((fail_count + 1))
            fi
        else
            fail_count=$((fail_count + 1))
        fi
        
        echo "----------------------------------------" | tee -a $LOG_FILE
    done
    
    # 显示总结
    log_info "导入完成!"
    log_info "成功: $success_count 个数据库"
    if [ $fail_count -gt 0 ]; then
        log_warn "失败: $fail_count 个数据库"
    fi
    
    # 显示所有导入的数据库
    log_info "新服务器上的数据库列表:"
    mysql -h $NEW_DB_HOST -P $NEW_DB_PORT -u $NEW_DB_USER -p$NEW_DB_PASS -e "SHOW DATABASES;" | tee -a $LOG_FILE
}

# 执行主函数
main

三、按表备份

bash 复制代码
#!/bin/bash
# 远程MySQL数据库同步(导出+导入)
# 源数据库(要导出的数据库)
SRC_HOST="源数据库ip地址"
SRC_USER="源数据库用户名"
SRC_PASS="源数据库密码"
SRC_DB="源数据库表名称"

# 目标数据库(要导入的数据库)
DST_HOST="目标数据库ip地址"
DST_USER="目标数据库用户名"
DST_PASS="目标数据库密码"
DST_DB="目标数据库表名称"

# 临时目录
TEMP_DIR="./temp_backup_$(date +%Y%m%d_%H%M%S)"
mkdir -p $TEMP_DIR

echo "=== 开始数据库同步 ==="
echo "从: $SRC_HOST.$SRC_DB"
echo "到: $DST_HOST.$DST_DB"

# 从源数据库导出
echo "正在从源数据库导出..."
TABLES=$(mysql -h $SRC_HOST -u $SRC_USER -p$SRC_PASS $SRC_DB -N -e "SHOW TABLES;")
for TABLE in $TABLES; do
    echo "导出: $TABLE"
    mysqldump -h $SRC_HOST -u $SRC_USER -p$SRC_PASS $SRC_DB $TABLE > $TEMP_DIR/$TABLE.sql
done

# 导入到目标数据库
echo "正在导入到目标数据库..."
for SQL_FILE in $TEMP_DIR/*.sql; do
    TABLE_NAME=$(basename $SQL_FILE .sql)
    echo "导入: $TABLE_NAME"
    mysql -h $DST_HOST -u $DST_USER -p$DST_PASS $DST_DB < $SQL_FILE
done

# 清理临时文件
rm -rf $TEMP_DIR

echo "同步完成! 共处理 $(echo "$TABLES" | wc -l) 个表"

四、大SQL按表拆分为小SQL文件

bash 复制代码
#!/bin/bash

# SQL文件拆分脚本 - 按表拆分
# 用法: ./split_sql.sh <sql文件> [输出目录]

split_sql_by_tables() {
    local sql_file="$1"
    local output_dir="${2:-split_tables}"
    local current_table=""
    local output_file=""
    
    # 检查文件是否存在
    if [[ ! -f "$sql_file" ]]; then
        echo "错误: 文件 $sql_file 不存在"
        return 1
    fi
    
    # 创建输出目录
    mkdir -p "$output_dir"
    
    echo "开始拆分SQL文件: $sql_file"
    echo "输出目录: $output_dir"
    
    # 计数器
    local table_count=0
    
    # 逐行读取SQL文件
    while IFS= read -r line; do
        # 检测表创建语句
        if [[ "$line" =~ ^CREATE\ TABLE\ \`([^\`]+)\` ]]; then
            current_table="${BASH_REMATCH[1]}"
            output_file="$output_dir/${current_table}.sql"
            
            echo "创建表文件: ${current_table}.sql"
            table_count=$((table_count + 1))
            
            # 如果文件已存在,先删除(避免重复内容)
            if [[ -f "$output_file" ]]; then
                rm "$output_file"
            fi
        fi
        
        # 写入到当前表文件
        if [[ -n "$output_file" && -n "$current_table" ]]; then
            echo "$line" >> "$output_file"
        fi
        
    done < "$sql_file"
    
    echo "拆分完成!共处理 $table_count 个表"
    echo "文件保存在: $output_dir"
}

# 显示帮助信息
show_help() {
    echo "用法: $0 <SQL文件> [输出目录]"
    echo ""
    echo "示例:"
    echo "  $0 database.sql                  # 输出到 split_tables 目录"
    echo "  $0 database.sql table_files      # 输出到 table_files 目录"
    echo ""
    echo "功能: 将MySQL导出的SQL文件按表拆分成多个文件"
}

# 主程序
main() {
    # 检查参数
    if [[ $# -eq 0 ]] || [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then
        show_help
        exit 0
    fi
    
    local sql_file="$1"
    local output_dir="$2"
    
    # 执行拆分
    split_sql_by_tables "$sql_file" "$output_dir"
}

# 运行主程序
main "$@"
相关推荐
星光一影4 小时前
大型酒店管理系统源码(多酒店版)
mysql·php
czhc11400756634 小时前
LINUX1012 mysql GLIBC安装
数据库·mysql
小草儿7994 小时前
gbase8s之.net8连接8s之mysql模式(windows)demo
windows·mysql·.net
DemonAvenger4 小时前
深入 Redis Hash:从原理到实战,10 年经验的后端工程师带你玩转哈希结构
数据库·redis·性能优化
sakoba5 小时前
MySQL的json处理相关方法
android·学习·mysql·json
❥ღ Komo·5 小时前
PHP数据库操作全攻略
数据库·oracle
程序新视界5 小时前
MySQL的整体架构及功能详解
数据库·后端·mysql
ANYOLY5 小时前
MySQL索引指南
数据库·mysql
怪兽20146 小时前
Redis过期键的删除策略有哪些?
java·数据库·redis·缓存·面试