18 KiB
数据备份与恢复
1. 简介
所有备份数据都应放在非数据库本地,而且建议有多份副本
备份: 能够防止由于机械故障以及人为误操作带来的数据丢失,例如将数据库文件保存在了其它地方
冗余: 数据有多份冗余,但不等备份,只能防止机械故障还来的数据丢失,例如主备模式、数据库集群
备份考虑的因素:
- 数据的一致性
- 服务的可用性
分类一:
- 逻辑备份:备份的是建表、建库、插入等操作所执行SQL语句;适用于中小型数据库,效率相对较低(mysqldump)
- 物理备份:直接复制数据库文件,适用于大型数据库环境,不受存储引擎的限制,但不能恢复到不同的MySQL版本(tar、xtrabackup)
分类二:
- 热备份:数据库启动同时给客户端提供服务的情况下
- 冷备份:数据库要关掉或者不能给客户端提供服务
备份方案:
- 完全备份:备份所有数据
- 增量备份:每次备份上一次备份到现在产生的新数据
- 差异备份:只备份跟完整备份不一样的
2. tar 备份
注意:
备份期间,服务不可用
备份过程:完全物理备份
停止数据库
[root@mysql ~]# systemctl stop mysqld
tar备份数据
[root@mysql ~]# mkdir /backup
[root@mysql ~]# cd /var/lib/mysql
[root@mysql mysql]# tar -zvcf /backup/`date +%F`-mysql-all.tar.gz ./*
启动数据库(备份完成后启动数据库,继续为其他服务提供服务)
[root@mysql ~]# systemctl start mysqld
恢复过程:模拟数据丢失,恢复数据
停止数据库
[root@mysql ~]# systemctl stop mysqld
清理环境
[root@mysql ~]# rm -rf /var/lib/mysql/*
导入备份数据
[root@mysql ~]# tar xvf /backup/2025-03-12-mysql-all.tar.gz -C /var/lib/mysql/
[root@mysql ~]# chown mysql.mysql /var/lib/mysql/* -R
启动数据库(恢复后验证数据是否回复成功)
[root@mysql ~]# systemctl start mysqld
3. xtrabackup 备份
简介
percona-xtrabackup是开源免费的支持MySQL 数据库热备份的软件;能对InnoDB和XtraDB存储引擎的数据库非阻塞地备份;它不暂停服务创建Innodb热备份;为mysql做增量备份;在mysql服务器之间做在线表迁移;使创建replication更加容易;备份mysql而不增加服务器的负载
安装软件:
[root@mysql ~]# wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.7/binary/redhat/6/x86_64/percona-xtrabackup-24-2.4.7-1.el6.x86_64.rpm
[root@mysql ~]# yum -y localinstall percona-xtrabackup-24-2.4.7-1.el6.x86_64.rpm
完整备份
创建备份目录:
[root@mysql ~]# mkdir -p /xtrabackup/full/
备份:
[root@mysql ~]# innobackupex --user=root --password='Wxin@123456' /xtrabackup/full/
查看备份数据:
[root@mysql ~]# ls /xtrabackup/full/
2025-03-12_13-14-19
模拟数据丢失数据恢复:(以下操作模拟数据丢失)
丢失前数据库中的数据:
[root@mysql ~]# mysql -uroot -p'Wxin@123456'
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
5 rows in set (0.00 sec)
数据丢失:
[root@mysql ~]# systemctl stop mysqld
[root@mysql ~]# rm -rf /var/lib/mysql/*
[root@mysql ~]# rm -rf /var/log/mysqld.log
[root@mysql ~]# rm -rf /var/log/mysql-slow/slow.log (有则删除,无则不需要操作)
恢复前的验证:
[root@mysql ~]# innobackupex --apply-log /xtrabackup/full/2025-03-12_13-14-19/
恢复之前需要确认配置文件内有数据库目录指定,不然xtrabackup不知道恢复到哪里
[root@mysql ~]# cat /etc/my.cnf
datadir=/var/lib/mysql
恢复数据:
[root@mysql ~]# innobackupex --copy-back /xtrabackup/full/2025-03-12_13-14-19/
修改权限:
[root@mysql ~]# chown mysql.mysql /var/lib/mysql -R
启动服务:
[root@mysql ~]# systemctl start mysqld
验证:
[root@mysql ~]# mysql -uroot -p'Wxin@123456'
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
增量备份
注意:
在进行增量备份前先进行完整备份
原理:每次备份上一次备份到现在产生的新数据
案例:周一进行全备,周二到周天进行增量备份
完整备份:(周一)
[root@mysql ~]# innobackupex --user=root --password='Wxin@123456' /xtrabackup/full/
创建增量备份存放数据目录:
[root@mysql ~]# mkdir -p /xtrabackup/zeng
模拟数据增加:
mysql> create database test;
Query OK, 1 row affected (0.00 sec)
mysql> create table test.t1( id int, name varchar(30), age int, sex enum('m','f') );
Query OK, 0 rows affected (0.01 sec)
mysql> insert into test.t1 values(1,'zhangsan',22,'m');
Query OK, 1 row affected (0.01 sec)
mysql> insert into test.t1 values(2,'lisi',22,'f');
Query OK, 1 row affected (0.00 sec)
第一次增量备份:(周二)
[root@mysql ~]# innobackupex --user=root --password='Wxin@123456' --incremental /xtrabackup/zeng/ --incremental-basedir=/xtrabackup/full/2025-03-12_13-14-19/
第一次增量备份的数据:
[root@mysql ~]# ls /xtrabackup/zeng/
2025-03-12_13-35-42
模拟数据增加:
mysql> delete from t1 where id=2;
Query OK, 1 row affected (0.01 sec)
第二次增量备份:(周三)
[root@mysql ~]# innobackupex --user=root --password='Wxin@123456' --incremental /xtrabackup/zeng/ --incremental-basedir=/xtrabackup/zeng/2025-03-12_13-35-42/
第二次增量备份的数据:
[root@mysql ~]# ls /xtrabackup/zeng/
2025-03-12_13-35-42 2025-03-12_13-39-06
后面的增量备份重复上面的操作(略)
增量备份数据恢复流程:(需要模拟数据的丢失)
停止数据库:
[root@mysql ~]# systemctl stop mysqld
删除数据:
[root@mysql ~]# rm -rf /var/lib/mysql/*
[root@mysql ~]# rm -rf /var/log/mysqld.log
其他数据根据实际情况删除
依次重演回滚:
全备回滚:
[root@mysql ~]# innobackupex --apply-log --redo-only /xtrabackup/full/2025-03-12_13-14-19/
第一次增量回滚:
[root@mysql ~]# innobackupex --apply-log --redo-only /xtrabackup/full/2025-03-12_13-14-19/ --incremental-dir=/xtrabackup/zeng/2025-03-12_13-35-42/
第二次增量回滚:
[root@mysql ~]# innobackupex --apply-log --redo-only /xtrabackup/full/2025-03-12_13-14-19/ --incremental-dir=/xtrabackup/zeng/2025-03-12_13-39-06/
根据实际增量备份的次数回滚,可以想恢复到那个时间节点就回滚到那个时间节点,所有的回滚都给全备
恢复数据:
[root@mysql ~]# innobackupex --copy-back /xtrabackup/full/2025-03-12_13-14-19/
修改权限:
[root@mysql ~]# chown mysql.mysql /var/lib/mysql -R
启动数据库:
[root@mysql ~]# systemctl start mysqld
验证:
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
5 rows in set (0.00 sec)
mysql> use test;
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| t1 |
+----------------+
1 row in set (0.00 sec)
mysql> select * from t1;
+------+----------+------+------+
| id | name | age | sex |
+------+----------+------+------+
| 1 | zhangsan | 22 | m |
+------+----------+------+------+
1 row in set (0.00 sec)
差异备份
注意:
在进行增量备份前先进行完整备份
原理:只备份跟完整备份不一样的
案例:周一进行全备,周二到周天进行差异备份
完整备份:(周一)
[root@mysql ~]# mkdir /xtrabackup/full -p
[root@mysql ~]# innobackupex --use=root --password='Wxin@123456' /xtrabackup/full
创建增量备份存放数据目录:
[root@mysql ~]# mkdir -p /xtrabackup/XY
模拟数据增加:
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
mysql> create database test;
Query OK, 1 row affected (0.00 sec)
mysql> create table test.t1(
-> id int,
-> name varchar(20)
-> );
Query OK, 0 rows affected (0.01 sec)
第一次增量备份:(周二)
[root@mysql ~]# innobackupex --user=root --password='Wxin@123456' --incremental /xtrabackup/XY/ --incremental-basedir=/xtrabackup/full/2025-03-12_14-25-19/
第一次增量备份的数据:
[root@mysql ~]# ls /xtrabackup/XY/
2025-03-12_14-26-56
模拟数据增加:
mysql> insert into t1 values(1,'zhangsan');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t1 values(2,'lisi');
Query OK, 1 row affected (0.00 sec)
第二次增量备份:(周三)
[root@mysql ~]# innobackupex --user=root --password='Wxin@123456' --incremental /xtrabackup/XY/ --incremental-basedir=/xtrabackup/full/2025-03-12_14-25-19/
第二次增量备份的数据:
[root@mysql ~]# ls /xtrabackup/XY/
2025-03-12_14-26-56 2025-03-12_14-28-16
注意:后面的差异备份跟之前一样,根据需求可以继续差异备份
差异备份恢复流程:(模拟数据丢失)
停止数据库:
[root@mysql ~]# systemctl stop mysqld
删除数据:
[root@mysql ~]# rm -rf /var/lib/mysql/*
[root@mysql ~]# rm -rf /var/log/mysqld.log
重演数据回滚:
完整备份回滚:
[root@mysql ~]# innobackupex --apply-log --redo-only /xtrabackup/full/2025-03-12_14-25-19/
差异备份回滚(根据差异备份的原理,如果恢复所有数据只需要将最后依次差异回滚)
[root@mysql ~]# innobackupex --apply-log --redo-only /xtrabackup/full/2025-03-12_14-25-19/ --incremental-dir=/xtrabackup/XY/2025-03-12_14-26-56/
恢复数据:
[root@mysql ~]# innobackupex --copy-back /xtrabackup/full/2025-03-12_14-25-19/
修改权限:
[root@mysql ~]# chown mysql.mysql /var/lib/mysql -R
启动数据库:
[root@mysql ~]# systemctl start mysqld
验证:
mysql> use test;
mysql> select * from t1;
+------+----------+
| id | name |
+------+----------+
| 1 | zhangsan |
| 2 | lisi |
+------+----------+
2 rows in set (0.00 sec)
4. mysqldump 备份
数据库数据:
mysql> select * from t1;
+------+----------+------+------+
| id | name | sex | age |
+------+----------+------+------+
| 1 | zhangsan | f | 22 |
| 2 | lisi | m | 22 |
| 3 | wangwu | m | 22 |
| 4 | liliu | m | 22 |
| 5 | sanwu | m | 22 |
+------+----------+------+------+
5 rows in set (0.00 sec)
mysql> select * from t2;
+------+-------+
| id | name |
+------+-------+
| 1 | name1 |
| 2 | name2 |
| 3 | name3 |
+------+-------+
3 rows in set (0.01 sec)
mysql> select * from t3;
+------+------+
| id | age |
+------+------+
| 1 | 11 |
| 2 | 22 |
| 3 | 33 |
| 4 | 44 |
+------+------+
4 rows in set (0.00 sec)
备份表:(前提有库有表)
[root@mysql ~]# mysqldump -u root -p'Wxin@123456' test t1 > /root/mysql/t1.sql
删除表:
mysql> drop table test.t1;
Query OK, 0 rows affected (0.00 sec)
mysql> use test;
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| t2 |
| t3 |
+----------------+
2 rows in set (0.00 sec)
恢复表:(恢复之前模拟数据丢失)
[root@mysql ~]# mysql -uroot -p'Wxin@123456' test < /root/mysql/t1.sql
验证:
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| t1 |
| t2 |
| t3 |
+----------------+
3 rows in set (0.00 sec)
备份一个库:
[root@mysql ~]# mysqldump -u root -p'Wxin@123456' test > /root/mysql/ku1.sql
备份多个库:
[root@mysql ~]# mysqldump -u root -p'Wxin@123456' -B test test2 test3 > /root/mysql/kuall.sql
备份所有库:
[root@mysql ~]# mysqldump -u root -p'Wxin@123456' -A > /root/mysql/all.sql
数据恢复:
为保证数据一致性,应在恢复数据之前停止数据库对外的服务,停止binlog日志
binlog使用binlog日志恢复数据时也会产生binlog日志(如果开启的话,需要关闭)
mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)
模拟数据丢失
mysql> drop database test;
Query OK, 3 rows affected (0.01 sec)
mysql> drop database test2;
Query OK, 0 rows affected (0.00 sec)
mysql> drop database test3;
Query OK, 0 rows affected (0.01 sec)
[root@mysql ~]# mysql -uroot -p'Wxin@123456' -D test < /root/mysql/ku1.sql
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1049 (42000): Unknown database 'test'
出现该错误是因为在恢复的时候需要有库的存在
[root@mysql ~]# mysql -uroot -p'Wxin@123456' -e "create database test"
mysql: [Warning] Using a password on the command line interface can be insecure.
[root@mysql ~]# mysql -uroot -p'Wxin@123456' -D test < /root/mysql/ku1.sql
[root@mysql ~]# mysql -uroot -p'Wxin@123456' -e "create database test"
[root@mysql ~]# mysql -uroot -p'Wxin@123456' -e "create database test2"
[root@mysql ~]# mysql -uroot -p'Wxin@123456' -e "create database test3"
[root@mysql ~]# mysql -uroot -p'Wxin@123456' -D test test2 test3 < /root/mysql/kuall.sql
或者
mysql> source /k1.sql
5. binlog 日志备份
原理:日志方法备份恢复数据
日志默认存储位置:
rpm : /var/lib/mysql
编译: 安装目录的var下
产生日志:
方式一:编译安装
[root@mysql ~]# ./usr/local/mysql/bin/mysqld_safe --log-bin --user=mysql --server-id=1 &
查看binlog日志
[root@mysql ~]# mysqlbinlog slave2-bin.000001 -v --base64-output=decode-rows
时间点 : 141126 14:04:49
位置点 : at 106
方式二:rpm安装(永久)
[root@mysql ~]# vim /etc/my.cnf
log-bin=mylog
server-id=1 //做主从复制使用
[root@mysql ~]# systemctl restart mysqld
查看:
[root@mysql ~]# ls /var/lib/mysql
auto.cnf ib_logfile0 mysql.sock.lock
ca-key.pem ib_logfile1 performance_schema
ca.pem ibtmp1 private_key.pem
client-cert.pem mylog.000001 public_key.pem
client-key.pem mylog.index server-cert.pem
ib_buffer_pool mysql server-key.pem
ibdata1 mysql.sock sys
[root@mysql ~]# mysqlbinlog /var/lib/mysql/mylog.000001 -v --base64-output=decode-rows
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#250312 15:34:10 server id 1 end_log_pos 123 CRC32 0x5f281ad6 Start: binlog v 4, server v 5.7.30-log created 250312 15:34:10 at startup
# Warning: this binlog is either in use or was not closed properly.
ROLLBACK/*!*/;
# at 123
#250312 15:34:10 server id 1 end_log_pos 154 CRC32 0x014a2356 Previous-GTIDs
# [empty]
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
方法二:
mysql> show binlog events in "mylog.000001";
+--------------+-----+----------------+-----------+-------------+---------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+--------------+-----+----------------+-----------+-------------+---------------------------------------+
| mylog.000001 | 4 | Format_desc | 1 | 123 | Server ver: 5.7.30-log, Binlog ver: 4 |
| mylog.000001 | 123 | Previous_gtids | 1 | 154 | |
+--------------+-----+----------------+-----------+-------------+---------------------------------------+
2 rows in set (0.00 sec)
默认查看第一个
mysql> show binlog events;
+--------------+-----+----------------+-----------+-------------+---------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+--------------+-----+----------------+-----------+-------------+---------------------------------------+
| mylog.000001 | 4 | Format_desc | 1 | 123 | Server ver: 5.7.30-log, Binlog ver: 4 |
| mylog.000001 | 123 | Previous_gtids | 1 | 154 | |
+--------------+-----+----------------+-----------+-------------+---------------------------------------+
2 rows in set (0.00 sec)
数据恢复
根据时间点恢复数据:
[root@mysql ~]# mysqlbinlog --start-datetime='2025-3-12 15:34:10' --stop-datetime='2025-3-12 5:34:10' /var/lib/mysql/mylog.000001 | mysql -u root -pWxin@123456
根据位置点恢复数据:
mysql> show binlog events;
+--------------+-----+----------------+-----------+-------------+---------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+--------------+-----+----------------+-----------+-------------+---------------------------------------+
| mylog.000001 | 4 | Format_desc | 1 | 123 | Server ver: 5.7.30-log, Binlog ver: 4 |
| mylog.000001 | 123 | Previous_gtids | 1 | 154 | |
+--------------+-----+----------------+-----------+-------------+---------------------------------------+
2 rows in set (0.00 sec)
[root@mysql ~]# mysqlbinlog --start-position 123 --stop-position 154 /var/lib/mysql/mylog.000001 | mysql -u root -pWxin@123456