MySQL数据备份/迁移
前提:
- 务必确保装有同一发行版的两台服务器上安装了同一版本的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
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 奇怪的阿峰
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果