第七星尘的独立博客

MySQL数据库的自动复制脚本

前言

我们可能在某些情况下,总要复制mysql数据库。比如,从A服务器,复制到B服务器去。这种复制操作可能是为了迁移数据库,也可能是为了建立主从,又或者单纯只是为了备份。在复制MySQL数据库的过程中,经常需要手工操作数据库,例如登录数据库进行数据的导入导出。当数据库很大的时候,又得在每一步操作之间各种传输等待。这些操作不仅繁琐,还容易出错。尤其是在操作生产环境数据库时,总得小心翼翼,怕误操作导致数据丢失或损坏。

为了方便以及更可靠,我写了一个脚本来简化数据库的复制流程。使用脚本,只要简单输入数据库信息,便可自动复制。它的好处主要有以下几点:

  1. 便捷高效:脚本可以自动执行预设的操作步骤,大大减少手工操作的次数和时间。
  2. 减少误操作:通过预定义的脚本流程,减少了人为操作的风险。
  3. 易于复用:脚本可以多次使用,便于日后的数据库迁移工作。
  4. 性能不错:该脚本利用mysqldump进行数据导入导出,支持逐表进行管道传输,理论上可以处理较大的数据库。

下面是详细步骤:

创建迁移脚本

首先,我们需要创建一个新的脚本文件 vi sync_db.sh ,并在文件中填入以下内容:

#!/bin/bash

# 捕获退出信号,确保删除临时文件
cleanup() {
    rm -f "$mysqldump_config" "$mysql_config"
}
trap cleanup EXIT

# 检查是否安装了 mysqldump
if ! command -v mysqldump &> /dev/null; then
    echo "mysqldump 命令不存在。请安装 MySQL 客户端或在安装了 MySQL 的服务器上运行此脚本。"
    exit 1
fi

# 提示用户输入数据库参数的函数
prompt_db_parameters() {
    local db_type=$1
    local host_var=$2
    local port_var=$3
    local user_var=$4
    local pass_var=$5
    local name_var=$6

    read -p "请输入${db_type}数据库主机地址 (默认: 127.0.0.1): " input
    eval $host_var="${input:-127.0.0.1}"

    read -p "请输入${db_type}数据库端口号 (默认: 3306): " input
    eval $port_var="${input:-3306}"

    read -p "请输入${db_type}数据库用户名 (默认: root): " input
    eval $user_var="${input:-root}"

    read -sp "请输入${db_type}数据库密码: " input
    echo
    eval $pass_var="$input"

    read -p "请输入${db_type}数据库名称: " input
    eval $name_var="$input"
}

# 提示用户输入源数据库的参数
prompt_db_parameters "源" src_host src_port src_user src_pass src_db
# 提示用户输入目标数据库的参数
prompt_db_parameters "目标" dest_host dest_port dest_user dest_pass dest_db

# 显示输入信息供用户确认
echo "请确认以下信息是否正确:"
echo "源数据库主机地址: $src_host"
echo "源数据库端口号: $src_port"
echo "源数据库用户名: $src_user"
echo "源数据库名称: $src_db"
echo "目标数据库主机地址: $dest_host"
echo "目标数据库端口号: $dest_port"
echo "目标数据库用户名: $dest_user"
echo "目标数据库名称: $dest_db"

read -p "以上信息是否正确?按y会开始同步数据 (y/n): " confirm
if [ "$confirm" != "y" ]; then
    echo "操作取消。"
    exit 1
fi

# 使用临时的 MySQL 配置文件传递密码
mysqldump_config=$(mktemp)
cat <<EOF > "$mysqldump_config"
[client]
user=$src_user
password=$src_pass
host=$src_host
port=$src_port
EOF

mysql_config=$(mktemp)
cat <<EOF > "$mysql_config"
[client]
user=$dest_user
password=$dest_pass
host=$dest_host
port=$dest_port
EOF

# 检查目标数据库是否存在,如果不存在则尝试创建
db_exists=$(mysql --defaults-file="$mysql_config" -e "SHOW DATABASES LIKE '$dest_db';" | tail -n +2)
if [ -z "$db_exists" ]; then
    mysql --defaults-file="$mysql_config" -e "CREATE DATABASE $dest_db;"
    if [ $? -ne 0 ]; then
        echo "无法创建目标数据库,可能是权限不足。"
        exit 1
    fi
    echo "目标数据库已创建:$dest_db"
else
    # 检查目标数据库是否存在数据
    table_count=$(mysql --defaults-file="$mysql_config" -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='$dest_db';" | tail -n 1)
    if [ "$table_count" -gt 0 ]; then
        read -p "目标数据库存在数据,是否清空目标数据库后覆盖? (y/n): " clear_confirm
        if [ "$clear_confirm" != "y" ]; then
            echo "操作取消。"
            exit 1
        else
            mysql --defaults-file="$mysql_config" -e "DROP DATABASE IF EXISTS \`$dest_db\`; CREATE DATABASE \`$dest_db\`;"
        fi
    fi
fi

# 尝试锁定源数据库
mysql --defaults-file="$mysqldump_config" -e "FLUSH TABLES WITH READ LOCK;" "$src_db"
lock_result=$?
if [ $lock_result -ne 0 ]; then
    echo "没有锁定数据库权限,请自行确保关闭应用程序、不再往数据库写入新数据。"
    read -p "是否继续操作?按y会继续 (y/n): " continue_confirm
    if [ "$continue_confirm" != "y" ]; then
        echo "操作取消。"
        exit 1
    fi
else
    # 如果成功锁定,则设置一个标记以便在操作完成后解锁
    locked=1
fi

# 获取所有表名
tables=$(mysql --defaults-file="$mysqldump_config" -e "SHOW TABLES;" "$src_db" | tail -n +2)

# 尝试逐个表进行同步
for table in $tables; do
    echo "同步表:$table"
    mysqldump --defaults-file="$mysqldump_config" --single-transaction --quick --compress --net_buffer_length=16384 --max_allowed_packet=512M "$src_db" "$table" | mysql --defaults-file="$mysql_config" "$dest_db"
    sync_result=$?
    if [ $sync_result -ne 0 ]; then
        echo "同步表 $table 失败,请检查相关参数或网络连接。"
        exit 1
    fi
done

# 如果数据库成功被锁定,则解锁源数据库
if [ "${locked:-0}" -eq 1 ]; then
    mysql --defaults-file="$mysqldump_config" -e "UNLOCK TABLES;" "$src_db"
fi

echo "数据库同步成功!"

使用脚本

1 保存上述代码到文件 sync_db.sh 中。

2 运行脚本:

   sh sync_db.sh

脚本会提示你输入源数据库和目标数据库的连接信息,然后按照提示执行数据库复制操作。

注意事项

  1. 权限问题:确保使用root或具有足够权限的用户进行操作,避免因为权限不足导致的迁移失败。
  2. 锁定数据库:脚本会尝试锁定源数据库以防止数据在迁移过程中被修改,如果无法锁定,请确保停应用程序在迁移过程中不进行数据写入操作。
 如无特殊说明,本站皆为原创。转载请注明来自第七星尘的独立博客《MySQL数据库的自动复制脚本》

评论