前提:

  • 务必确保装有同一发行版的两台服务器上安装了同一版本的MySQL。
  • 务必确保两台服务器上都有足够的闲置空间,以保存数据库转储文件和导入的数据库。
  • 千万别考虑将数据库的data目录转移到另一台服务器上。别乱动数据库的内部结构,不然将来会出问题。
  • 数据备份时最好停库

停库

先登录进入到旧服务器,使用systemctl命令,停止mysql/mariadb服务,如下所示:

# systemctl stop mariadb  
OR  
# systemctl stop mysql  

docker:

docker stop mysql容器id

备份数据库

使用 mysqldump 命令,将所有MySQL数据库转储到一个文件

注意: mysqldump 命令需要安装有mysql客户端

mysqldump -hlocalhost -p3306 -uroot -p --all-databases > ./all_databases.sql
#OR
mysqldump -uroot -p --all-databases > ./all_databases.sql 

参数说明:

--all-databases, -A: 备份所有数据库
--databases, -B: 用于备份多个数据库,如果没有该选项,mysqldump把第一个名字参数作为数据库名,后面的作为表名。使用该选项,mysqldum把每个名字都当作为数据库名。
--no-data, -d:只导出表结构
--quick, -q:快速导出
--xml, -X:导出为xml文件

centos 7 仅安装mysql client

1、 添加rpm源

rpm -ivh https://repo.mysql.com//mysql57-community-release-el7-11.noarch.rpm

2、通过yum搜索

yum search mysql-community

3、导入秘钥

rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022

4、安装x64位的 mysql 客户端

yum install mysql-community-client.x86_64 -y

只备份一个库:

mysqldump -u root -p --opt database_name > ./database_name.sql 
#OR
mysqldump -u root -p --databases database_name > ./database_name.sql 

备份多个库:

mysqldump -u root -p --databases database_name1 database_name2 database_name3... > ./all_database.sql

备份压缩:

mysqldump -hlocalhost -p3306 -uroot -p --all-databases | gzip > all_databases.sql.gz

将MySQL数据库转储文件转移到新服务器

使用 scp 命令,将数据库转储文件转移到新服务器的主目录下,如下所示:

scp all_databases.sql user@example.com:/xxxx
scp database_name.sql user@example.com:/xxxx

将MySQL数据库转储文件导入到新服务器

一旦MySQL转储文件转移到了新服务器,可以使用下列命令将所有数据库导入到MySQL。

方法一 :直接在shell中使用命令行

mysql -hlocalhost -p3306 -uroot -p < xxxx.sql

方法二 :可以进入 MySQL,在 MySQL命令行下面用source导入

source /xxxx.sql

还原压缩的MySQL数据库

gunzip < all_databases.sql.gz | mysql -hlocalhost -p3306 -uroot -p

将MySQL数据库和用户转移到新服务器

如果想把所有的MySQL数据库、用户、权限和数据结构从旧服务器统统转移到新服务器,可以使用rsync命令,将来自mysql/mariadb数据目录的所有内容转移到新服务器

rsync -avz /var/lib/mysql/* user@example.com:/var/lib/mysql/ 

一旦转移完成,可以将mysql/mariadb数据目录设成归用户mysql和用户组mysql所有,然后列出目录,检查所有文件已转移过去。

chown mysql:mysql -R /var/lib/mysql/  
ls -l /var/lib/mysql/  

分文件备份脚本

#/bin/bash

for dbname in `mysql -uroot -p'xxxxxx' -e "show databases;"|grep -Evi "database|infor|perfor"`
do
echo $dbname
mysqldump -uroot -p'xxxxx'  -B $dbname|gzip >./bak/${dbname}.sql.gz
done

进一步完善的脚本

#!/bin/bash

source /etc/profile           #加载系统环境变量
source ~/.bash_profile    #加载用户环境变量
set -o nounset             #引用未初始化变量时退出
#set -o errexit             #执行shell命令遇到错误时退出

user="root"
password="xxxxxx"
host="localhost"
port="3306"

#排除不需要备份数据库,数组
excluded_dbs=(
"demo"
#"demo0"
"demo1"
)

#备份时加锁方式,
#MyISAM为锁表--lock-all-tables,
#InnoDB为锁行--single-transaction
lock="--single-transaction"
mysql_path="/usr/local/mysql"
date=$(date +%Y-%m-%d_%H-%M-%S)
backup_path="${mysql_path}/backup/${date}"
day=15
backup_log="${mysql_path}/backup.log"

#建立备份目录
if [ ! -e $backup_path ];then
    mkdir -p $backup_path
fi


#删除以前备份
#  find $mysql_path/backup -type d -mtime +15 -exec rm -r {} \; > /dev/null 2>&1
# 获取文件夹的创建时间
create_time=$(sudo debugfs -R 'stat <$(stat -c %i '$mysql_path/backup')>' /dev/sda1 | grep crtime | awk '{print $7, $8}')

# 将创建时间转换为秒数
create_timestamp=$(date -d "$create_time" +%s)

# 获取当前时间的秒数
current_timestamp=$(date +%s)

# 计算两个时间之间的差值(以天为单位)
days_diff=$(( (current_timestamp - create_timestamp) / (60 * 60 * 24) ))

# 如果文件夹的创建时间早于15天前,则删除它
if [ $days_diff -gt 15 ]; then
  sudo rm -r $dir_path
fi


echo "开始备份数据库,已排除:${excluded_dbs[*]}"

#备份并压缩
backup_sql(){
    dbname=$1
    backup_name="${dbname}.sql"
    #-R备份存储过程,函数,触发器
    mysqldump -h $host -P $port -u $user -p$password $lock --default-character-set=utf8 --flush-logs -R $dbname > $backup_path/$backup_name    
    if [[ $? == 0 ]];then
        cd $backup_path
        tar zcpvf $backup_name.tar.gz $backup_name
        size=$(du $backup_name.tar.gz -sh | awk '{print $1}')
        rm -rf $backup_name
        echo "$date 备份 $dbname($size) 成功 "
    else
        cd $backup_path
        rm -rf $backup_name
        echo "$date 备份 $dbname 失败 "
    fi
}

#查询排除后的数据库列表
databases=($(mysqlshow -P $port -u $user -p$password | awk '{ print $2 }' | grep -v "^Database$" | grep -vwE "$(echo ${excluded_dbs[@]} | sed 's/ /|/g')"))


#循环备份
for db in ${databases[@]}; do
     backup_sql ${db} >> $backup_log 2>&1
done

echo "备份结束,结果查看 $backup_log"
du $backup_path/* -sh | awk '{print "文件:" $2 ",大小:" $1}'

分文件导入

#!/bin/bash

user="root"
password="xxxxx"
host="localhost"
port="3306"

date=$(date +%Y-%m-%d_%H-%M-%S)

do_import(){
	sql_file_name=$1
	echo "$date 正在导入 $sql_file_name..."
	gzip -dc < $sql_file_name | mysql -h $host -P $port -u $user -p$password --default-character-set=utf8
	echo "$date 导入 $sql_file_name 完成"
	echo ""
}

for SQL in ./*.sql.gz; 
do
	 do_import $SQL >> ./import_log 2>&1
done

https://blog.51cto.com/lee90/1757419