Mysql备份与恢复
...大约 10 分钟
本文主要记录在centos7.9备份mysql8.0方法
一 通过mysqldump备份
此备份为逻辑备份
mysqldump重要参数说明
- --single-transaction:在备份开始前,先执行 START TRANSACTION命令,以此来获得备份的一致性,当前该参数只对 InnoDB存储引擎有效。当启用该参数并进行备份时,确保没有其他任何的DDL语句执行,因为一致性读并不能隔离DDL操作。
- --lock-tables(-1):在备份中,依次锁住每个架构下的所有表。一般用于 MyIsAM存储引擎,当备份时只能对数据库进行读取操作,不过备份依然可以保证一致性。对于 InnoDB存储引擎,不需要使用该参数,用- - single-transaction即可。并且--lock-tables和--single-transaction是互斥( exclusive)的,不能同时使用。如果用户的 MySQL数据库中,既有 MyISAM存储引擎的表,又有 InnoDB存储引擎的表,那么这时用户的选择只有--lock-tables了。此外,正如前面所说的那样,--lock-tables选项是依次对每个架构中的表上锁的,因此只能保证每个架构下表备份的一致性,而不能保证所有架构下表的一致性。
- --lock--all-tables(-x):在备份过程中,对所有架构中的所有表上锁。这个可以避免之前说的- lock-tables参数不能同时锁住所有表的问题。
- -add-dop-database:在 CREATE DATABASE前先运行 DROP DATABASE。这个参数需要和--all-databases或者--databases选项一起使用。在默认情况下,导出的文本文件中并不会有 CREATE DATABASE,除非指定了这个参数。
- --master-data[=value]:通过该参数产生的备份转存文件主要用来建立一个replication。当value的值为1时,转存文件中记录CHANGE MASTER语句。当value的值为2时, CHANGE MASTER语句被写出SQL注释。在默认情况下,value的值为空。当 value值为1时,在备份文件中会看到:CHANGE MASTER TO MASTER_LOG_FILE='xen-server-bin.000006',MASTER_LOG_POS=8095;当 value为2时,在备份文件中会看到 CHANGE MASTER语句被注释了。
- --master-data:会自动忽略--lock-tables选项。如果没有使用--single-transaction选项,则会自动使用--lock-all-tables选项。
- --events(-E):备份事件调度器。
- --routines(-R):备份存储过程和函数。
- --triggers:备份触发器。
- --hex-blob:将 BINARY、 VARBINARY、BLOG和BIT列类型备份为十六进制的格式。 mysqldump导出的文件一般是文本文件,但是如果导出的数据中有上述这些类型,在文本文件模式下可能有些字符不可见,若添加--hex-blob选项,结果会以十六进制的方式显示。
- --tab=path(- T path):产生TAB分割的数据文件。对于每张表, mysqldump创建一个包含 CREATE TABLE语句的 table_name. sql文件,和包含数据的tbl_name. txt文件。可以使用--fields-terminated-by=.…,--fields-enclosed-by=.…,--fields-optionally-enclosed-by=....,--fields-escaped-by=....,--lines-terminated-by=....来改变默认的分割符、换行符等。
备份过程
- 先发出一条 flush tables 关闭实例上所有打开的表
- 创建一个全局锁,FLUSH TABLES WITH READ LOCK获得 db 一致性状态。
- 设置事务隔离级别为 RR ,确保备份事务中任何时刻的数据都相同。
- 创建一个 RR 级别的事务一致性快照 ,执行START TRANSACTION
/*!40100 WITH CONSISTENT SNAPSHOT */
- 根据参数–master-data=2 打印 SHOW MASTER STATUS 获取文件名和位置点信息。
- 执行UNLOCK TABLES 释放锁。
- 在开始做所有的事情之前创建了一个事务的还原点,然后先备份一张表,然后再回到事务的还原点,再继续备份下一张表,一直这样重复直到所有的表备份完成。最后把事务还原点释放掉。然后把这个事务 rollback 掉就可以了。
优缺点
优点:
mysqldump的优点就是逻辑备份,把数据生成SQL形式保存,在单库,单表数据迁移,备份恢复等场景方便,SQL形式的备份文件通用,也方便在不同数据库之间移植。对于InnoDB表可以在线备份。
缺点:
mysqldump是单线程,数据量大的时候,备份时间长,甚至有可能在备份过程中非事务表长期锁表对业务造成影响(SQL形式的备份恢复时间也比较长)。mysqldump备份时会查询所有的数据,这可能会把内存中的热点数据刷掉
开始备份
新建mysqlbackup.sh
文件,贴入以下内容,注意更换主机地址、帐号、密码
#!/bin/bash
# 备份数据库
database_name=$1
# 保存备份个数,备份31天数据
number=31
# 备份保存路径
backup_dir=/data/backup/mysql/$database_name
# 日期
dd=`date +%Y-%m-%d-%H-%M-%S`
# 备份工具
tool=mysqldump
# 主机地址
dbhost=127.0.0.1
# 端口
dbport=3306
# 用户名
username=你的数据库用户名
# 密码
password="你的数据库连接密码"
# 如果文件夹不存在则创建
if [ ! -d $backup_dir ];
then
mkdir -p $backup_dir
fi
# 开始备份
$tool -h$dbhost -P$dbport -u$username -p$password $database_name > $backup_dir/$database_name-$dd.sql
# 写创建备份日志
echo "create $backup_dir/$database_name-$dd.sql" >> $backup_dir/log.txt
# 找出要删除的备份
delfile=`ls -l $backup_dir/$database_name-*.sql|awk '{print $9}' |head -1`
# 判断现在的备份是否大于$number
count=`ls -l $backup_dir/$database_name-*.sql |awk '{print $9}' |wc -l`
if [ $count -gt $number ];
then
# 删除最早生成的备份,只保留number数量的备份
rm $delfile
# 写删除日志文件
echo "delete $delfile" >> $backup_dir/log.txt
fi
在linux上可以配置定时任务执行以上脚本,如:
chmod +x mysqlbackup.sh
0 2 * * * /root/mysqlbackup.sh
开始恢复数据
先命令行登录数据库
[root@server-test ~]# mysql -uroot -p
mysql> use 您的数据库名
mysql> source 备份文件路径
二 通过percona xtraBackup8.x备份
更多详细信息查看官网文档
安装
安装percona xtraBackup仓库
[root@server-test ~]# yum install -y https://repo.percona.com/yum/percona-release-latest.noarch.rpm
执行安装
[root@server-test ~]# yum install percona-xtrabackup-80.x86_64
备份前准备
开启MySQL二进制日志
[root@server-test ~]# vi /etc/my.conf
[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove the leading "# " to disable binary logging
# Binary logging captures changes between backups and is enabled by
# default. It's default setting is log_bin=binlog
# disable_log_bin
log_bin=binlog
default-authentication-plugin=mysql_native_password
binlog
为文件名,详细目录为:/var/lib/mysql/binlog.000001
、/var/lib/mysql/binlog.index
命令行登录MySQL
[root@server-test ~]# mysql -uroot -p
mysql> show variables like 'log_bin'
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin | ON |
+---------------+-------+
出现以上结果表示,binlog已经开启
完整备份还原流程
备份
[root@server-test ~]# mkdir /data/backup/mysql/full/
[root@server-test ~]# xtrabackup --backup=1 --port=3306 --databases=testdb --target-dir=/data/backup/mysql/xtrabackup/full/ --user=root --password
执行以上命令后如果出现以下错误,按照下面的处理方法处理即可:
错误1:
failed to execute query 'LOCK INSTANCE FOR BACKUP' : 1227 (42000) Access denied; you need (at least one of) the BACKUP_ADMIN privilege(s) for this operation
处理方法:
登录mysql
[root@server-test ~]# mysql -uroot -p
mysql> grant BACKUP_ADMIN on *.* to 'root'@'%'
mysql> FLUSH PRIVILEGES;
mysql> exit
错误2:
Failed to connect to MySQL server: DBI connect(';mysql_read_default_group=xtrabackup;port=3306','root',...) failed: Authentication plugin 'caching_sha2_password' cannot be loaded: /usr/lib64/mysql/plugin/caching_sha2_password.so
登录mysql
[root@server-test ~]# mysql -uroot -p
mysql> ALTER USER 'root'@'%' IDENTIFIED BY '你的密码' PASSWORD EXPIRE NEVER;
mysql> ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '你的密码';
mysql> FLUSH PRIVILEGES;
mysql> exit
处理完上述错误后,重新执行备份命令即可
还原
先停止数据库
[root@server-test ~]# systemctl stop mysqld
模拟数据库损坏(慎用)
[root@server-test ~]# rm -rf /var/lib/mysql/*
[root@server-test ~]# rm -rf /var/log/mysqld.log
还原一致性检查
[root@server-test ~]# xtrabackup --prepare --target-dir=/data/backup/mysql/full/
开始恢复
[root@server-test ~]# xtrabackup --copy-back --target-dir=/data/backup/mysql/full/
还原后要给mysql用户再授权
[root@server-test ~]# chown -R mysql.mysql /var/lib/mysql
[root@server-test ~]# systemctl start mysqld
增量备份还原流程
备份
# 基于完整备份生成第一次增量备份。
[root@server-test ~]# xtrabackup -uroot -p'mysql-root用户密码' --backup --target-dir=/data/backup/mysql/inc1 --incremental-basedir=/data/backup/mysql/full
# 基于第一次增量备份生成第二次增量备份
[root@server-test ~]# xtrabackup -uroot -p'mysql-root用户密码' --backup --target-dir=/data/backup/mysql/inc2 --incremental-basedir=/data/backup/mysql/inc1
还原
# 先stop mysqld
[root@server-test ~]# systemctl stop mysqld
# 再进行一致性检查(先回滚全量包,再回滚第一次增量包,再回滚第二次增量包,这时增量数据都到了全量包中)【每次增量包都要回滚!】
[root@server-test ~]# xtrabackup --prepare --apply-log-only --target-dir=/data/backup/mysql/full
[root@server-test ~]# xtrabackup --prepare --apply-log-only --target-dir=/data/backup/mysql/full --incremental-dir=/data/backup/mysql/inc1
[root@server-test ~]# xtrabackup --prepare --apply-log-only --target-dir=/data/backup/mysql/full --incremental-dir=/data/backup/mysql/inc2
# 回滚完成后,进行恢复
[root@server-test ~]# xtrabackup --copy-back --target-dir=/data/backup/mysql/full
# 授权文件权限
[root@server-test ~]# chown -R mysql.mysql /var/lib/mysql
# 重启服务
[root@server-test ~]# systemctl restart mysqld
差异备份还原流程
备份
# 基于完全备份生成第一次增量备份,与完全备份的差异就是差异备份
[root@server-test ~]# xtrabackup -uroot -p'mysql-root用户密码' --backup --target-dir=/data/backup/mysql/inc1 --incremental-basedir=/data/backup/mysql/full
# 仍是基于完全备份生成第二次增量备份,与完全备份的差异就是差异备份。(后续的差异备份仍是基于完全备份进行,以此类推。)
[root@server-test ~]# xtrabackup -uroot -p'mysql-root用户密码' --backup --target-dir=/data/backup/mysql/inc2 --incremental-basedir=/data/backup/mysql/inc1
如上所示,进行了两次差异备份,那么回滚不用像增量备份一样,每个增量包都需要回滚,只需回归完全备份包和最后一次差异备份包即可。
[root@server-test ~]# xtrabackup --prepare --apply-log-only --target-dir=/data/backup/mysql/full
[root@server-test ~]# xtrabackup --prepare --apply-log-only --target-dir=/data/backup/mysql/full --incremental-dir=/data/backup/mysql/inc2
# 回滚完成后,进行恢复
[root@server-test ~]# xtrabackup --copy-back --target-dir=/data/backup/mysql/full
# 授权文件权限
[root@server-test ~]# chown -R mysql.mysql /var/lib/mysql
# 重启服务
[root@server-test ~]# systemctl restart mysqld
完整备份shell例子:
#!/bin/bash
# 备份数据库
database_name=$1
# --parallel:指定备份使用的线程数
bakthreads=4
# 保存备份个数,备份31天数据
number=31
# 备份保存路径
backup_dir=/data/backup/mysql/xtrabackup/full/$database_name
# 日期
dd=`date +%Y-%m-%d-%H-%M-%S`
# 备份工具
tool=xtrabackup
# 主机地址
dbhost=127.0.0.1
# 端口
dbport=3306
# 用户名
username=你的数据库用户名
# 密码
password="你的数据库连接密码"
# 如果文件夹不存在则创建
if [ ! -d $backup_dir ];
then
mkdir -p $backup_dir
fi
# 开始备份
$tool --backup=1 --host=$dbhost --port=$dbport --user=$username --password=$password --databases=$database_name --target-dir=$backup_dir/$dd --parallel=$bakthreads
# 写创建备份日志
echo "create $backup_dir/$dd" >> $backup_dir/log.txt
# 找出要删除的备份
delfile=`ls -l $backup_dir |grep "^d" |awk '{print $NF}' |head -1`
# 判断现在的备份是否大于$number
count=`ls -l $backup_dir |grep "^d" |awk '{print $NF}' |wc -l`
if [ $count -gt $number ];
then
# 删除最早生成的备份,只保留number数量的备份
rm -rf $backup_dir/$delfile
# 写删除日志文件
echo "delete $backup_dir/$delfile" >> $backup_dir/log.txt
fi
三 二进制日志备份与恢复
修改配置文件启用二进制日志
[root@server-test ~]# vi /etc/my.conf
[mysqld]
log-bin=mysql-bin
sync_binlog=1
innodb_support_xa=1
备份二进制日志
在备份二进制日志文件前,可以通过 FLUSH LOGS命令来生成一个新的二进制日志文件,然后备份之前的二进制日志。
恢复二进制日志
[root@server-test ~]# mysqlbinlog [options] log file
# 例如要还原binlog.000001,执行如下命令
[root@server-test ~]# mysqlbinlog binlog.000001 | mysql -uroot -p
# 如果需要恢复多个二进制日志文件,最正确的做法应该是同时恢复多个二进制日志文件,而不是一个一个地恢复,如:
[root@server-test ~]# mysqlbinlog binlog.[0-10]* | mysql -uroot -p
# 也可以先通过 mysqlbinlog命令导出到一个文件,然后再通过 SOURCE命令来导人,这种做法的好处是可以对导出的文件进行修改后再导入,如
[root@server-test ~]# mysqlbinlog binlog.000001 > /tmp/test.sql
[root@server-test ~]# mysqlbinlog binlog.000002 >> /tmp/test.sql
[root@server-test ~]# mysql -u root -p -e "source /tmp/statements.sql"
# --start-position和--stop-position选项可以用来指定从二进制日志的某个偏移量来进行恢复,这样可以跳过某些不正确的语句,如:
[root@server-test ~]# mysqlbinlog --start-position 12345 binlog.0000001 | mysql-uroot -p
# --start-datetime和--stop-datetime选项可以用来指定从二进制日志的某个时间点来进行恢复,用法和--start-position和--stop-position选项基本相同。
Powered by Waline v2.15.5