这里写目录标题
mysqldump备份结合binlog日志恢复
MySQL备份一般采取全库备份加日志备份的方式,例如每天执行一次全备份,每小时执行一次二进制日志备份。这样在MySQL故障后可以使用全备份和日志备份将数据恢复到最后一个二进制日志备份前的任意位置或时间。
一、binlog介绍
mysql的二进制日志记录着该数据库的所有增删改的操作日志(前提是要在自己的服务器上开启binlog),还包括了这些操作的执行时间。为了显示这些二进制内容,我们可以使用mysqlbinlog命令来查看。 Binlog的用途
1.主从同步
2.恢复数据库
开启binary log功能 通过编辑my.cnf中的log-bin选项可以开启二进制日志;
形式如下: log-bin[=DIR/[filename]](配置文件中只写log_bin不写后面的文件名和路径时,默认存放在/usr/local/mysql/data目录下,文件名为主机名-bin.000001…命名) 其中,DIR参数指定二进制文件的存储路径;filename参数指定二级制文件的文件名,其形式为filename.number,number的形式为000001、000002等。每次重启mysql服务或运行mysql> flush logs;都会生成一个新的二进制日志文件,这些日志文件的number会不断地递增。除了生成上述的文件外还会生成一个名为filename.index的文件。这个文件中存储所有二进制日志文件的清单又称为二进制文件的索引 配置保存以后重启mysql的服务器。
用mysql> show variables like ‘log_bin’;查看bin-log是否开启。
查看产生的binary log 注:查看binlog内容是为了恢复数据 bin-log因为是二进制文件,不能通过文件内容查看命令直接打开查看,mysql提供两种方式查看方式,在介绍之前,我们先对数据库进行一下增删改的操作,否则log里边数据有点空。
[root@mysql ~]# mysql -uroot -p123.com -e "reset master" // 清空所有的二进制文件,从00001开始
[root@mysql ~]# mysql -uroot -p123.com -e "create database test"
[root@mysql ~]# mysql -uroot -p123.com -e "use test;create table tb1(id int primary key auto_increment,name varchar(20))"
[root@mysql ~]# mysql -uroot -p123.com -e "insert into test.tb1(name) values ('lisi')"
[root@mysql ~]# mysql -uroot -p123.com -e "insert into test.tb1(name) values ('zhangsan')"
重新开始一个新的日志文件
[root@mysql ~]# mysql -uroot -p123.com -e "flush logs"
[root@mysql ~]# mysql -uroot -p123.com -e "delete from test.tb1 where id=2"
[root@mysql ~]# mysql -uroot -p123.com -e "insert into test.tb1(name) values ('tom')"
[root@mysql ~]# mysql -uroot -p123.com -e "select * from test.tb1"
+----+------+
| id | name |
+----+------+
| 1 | lisi |
| 3 | tom |
+----+------+
查看MySQL Server上的二进制日志
mysql> show binary logs;
+--------------+-----------+
| Log_name | File_size |
+--------------+-----------+
| mysql.000001 | 1083 |
| mysql.000002 | 673 |
+--------------+-----------+
2 rows in set (0.00 sec)
查看二进制日志信息的命令:
语法格式:SHOW BINLOG EVENTS[IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count] 查看二进制日
志中的事件
mysql> show binlog events\G;
默认显示可找到的第一个二进制日志文件中的事件,包含了日志文件名、事件的开始位置、事件类型、结束位置、信息等内容
*************************** 1. row ***************************
Log_name: mysql.000001
Pos: 4
Event_type: Format_desc //此事件为格式描述事件
Server_id: 1
End_log_pos: 123
Info: Server ver: 5.7.32-log, Binlog ver: 4
*************************** 2. row ***************************
Log_name: mysql.000001
Pos: 123
Event_type: Previous_gtids
Server_id: 1
End_log_pos: 154
Info:
*************************** 3. row ***************************
Log_name: mysql.000001
Pos: 154
Event_type: Anonymous_Gtid
Server_id: 1
End_log_pos: 219
Info: SET @@SESSION.GTID_NEXT= 'ANONYMOUS'
*************************** 4. row ***************************
Log_name: mysql.000001
Pos: 219
Event_type: Query //为查询事件
Server_id: 1
End_log_pos: 313
Info: create database test
*************************** 5. row ***************************
Log_name: mysql.000001
Pos: 313
Event_type: Anonymous_Gtid
Server_id: 1
End_log_pos: 378
Info: SET @@SESSION.GTID_NEXT= 'ANONYMOUS'
*************************** 6. row ***************************
Log_name: mysql.000001
Pos: 378
Event_type: Query
Server_id: 1
End_log_pos: 520
Info: use `test`; create table tb1(id int primary key auto_incre
*************************** 7. row ***************************
Log_name: mysql.000001
Pos: 520
Event_type: Anonymous_Gtid
Server_id: 1
End_log_pos: 585
Info: SET @@SESSION.GTID_NEXT= 'ANONYMOUS'
*************************** 8. row ***************************
Log_name: mysql.000001
Pos: 585
Event_type: Query //为查询事件,事务开始
Server_id: 1
End_log_pos: 653
Info: BEGIN
*************************** 9. row ***************************
Log_name: mysql.000001
Pos: 653
Event_type: Table_map //为表映射事件
Server_id: 1
End_log_pos: 702
Info: table_id: 108 (test.tb1)
*************************** 10. row ***************************
Log_name: mysql.000001
Pos: 702
Event_type: Write_rows
Server_id: 1
End_log_pos: 747
Info: table_id: 108 flags: STMT_END_F
*************************** 11. row ***************************
Log_name: mysql.000001
Pos: 747
Event_type: Xid
Server_id: 1
End_log_pos: 778
Info: COMMIT /* xid=29 */
*************************** 12. row ***************************
Log_name: mysql.000001
Pos: 778
Event_type: Anonymous_Gtid
Server_id: 1
End_log_pos: 843
Info: SET @@SESSION.GTID_NEXT= 'ANONYMOUS'
*************************** 13. row ***************************
Log_name: mysql.000001
Pos: 843
Event_type: Query
Server_id: 1
End_log_pos: 911
Info: BEGIN
*************************** 14. row ***************************
Log_name: mysql.000001
Pos: 911
Event_type: Table_map
Server_id: 1
End_log_pos: 960
Info: table_id: 108 (test.tb1)
*************************** 15. row ***************************
Log_name: mysql.000001
Pos: 960
Event_type: Write_rows
Server_id: 1
End_log_pos: 1009
Info: table_id: 108 flags: STMT_END_F
*************************** 16. row ***************************
Log_name: mysql.000001
Pos: 1009
Event_type: Xid
Server_id: 1
End_log_pos: 1040
Info: COMMIT /* xid=32 */
*************************** 17. row ***************************
Log_name: mysql.000001
Pos: 1040
Event_type: Rotate
Server_id: 1
End_log_pos: 1083
Info: mysql.000002;pos=4
17 rows in set (0.00 sec)
该命令还包含其他选项以便灵活查看
mysql> show binlog events in 'mysql.000002' from 219 limit 1,3\G //limit1,1为偏移量
*************************** 1. row ***************************
Log_name: mysql.000002
Pos: 287
Event_type: Table_map
Server_id: 1
End_log_pos: 336
Info: table_id: 108 (test.tb1)
*************************** 2. row ***************************
Log_name: mysql.000002
Pos: 336
Event_type: Delete_rows
Server_id: 1
End_log_pos: 385
Info: table_id: 108 flags: STMT_END_F
*************************** 3. row ***************************
Log_name: mysql.000002
Pos: 385
Event_type: Xid
Server_id: 1
End_log_pos: 416
Info: COMMIT /* xid=38 */
3 rows in set (0.00 sec)
SHOW BINARY LOGS 等价于 SHOW MASTER LOGS PURGE BINARY LOGS用于删除二进制日志,如: PURGE
BINARY LOGS TO ‘mysql-bin.00010’; //把这个文件之前的其他文件都删除掉 PURGE BINARY LOGS BEFORE
‘2016-08-28 22:46:26’;//把指定时间之前的二进制文件删除了 RESET MASTER 与 RESET SLAVE 前者清空index文
件中列出的所有二进制日志,重置index文件为空,并创建一个新的二进制日志文件,一般用于MASTER首次启
动时。后者使SLAVE忘记其在MASTER二进制日志文件中的复制位置,它会删除master.info、relay-log.info 和所
有中继日志文件并开始一个新的中继日志文件,以便于开始一个干净的复制。在使用RESET SLAVE前需先关闭
SLAVE复制线程。 上述方式可以查看到服务器上存在的二进制日志文件及文件中的事件,但是想查看到文件中
具体的内容并应于恢复场景还得借助mysqlbinlog这个工具。
语法格式: mysqlbinlog [options] log_file … 输出内容会因日志文件的格式以及mysqlbinlog工具使用的选项不同而略不同。 mysqlbinlog的可用选项可参考man手册。 二进制日志文件的格式包含行模式、语句模式和混合模式(也即有服务器决定在什么情况下记录什么类型的日志),基于语句的日志中事件信息包含执行的语句等,基于行的日志中事件信息包含的是行的变化信息等。混合模式的日志中两种类型的事件信息都会记录。 为了便于查看记录了行变化信息的事件在当时具体执行了什么样的SQL语句可以使用mysqlbinlog工具的-v(–verbose)选项,该选项会将行事件重构成被注释掉的伪SQL语句,如果想看到更详细的信息可以将该选项给两次如-vv,这样可以包含一些数据类型和元信息的注释内容,如 先切换到binlog所在的目录下
[root@mysql ~]# cd /usr/local/mysql/data/
[root@mysql data]# mysqlbinlog mysql.000001
[root@mysql data]# mysqlbinlog -v mysql.000001 #能查看在表里做了什么
[root@mysql data]# mysqlbinlog -vv mysql.000001 #能够更详细的查看做了什么
另外mysqlbinlog和可以通过–read-from-remote-server选项从远程服务器读取二进制日志文件,这时需要一些而外的连接参数,
如-h,-P,-p,-u等,这些参数仅在指定了–read-from-remote-server后有效。
无论是本地二进制日志文件还是远程服务器上的二进制日志文件,无论是行模式、语句模式还是混合模式的二进制日志文件,被mysqlbinlog工具解析后都可直接应用与MySQL Server进行基于时间点、位置或数据库的恢复。
下面我们就来演示如何使用binlog恢复之前删除数据(id=2那条记录) 注意:在实际生产环境中,如果遇到需要恢复数据库的情况,不要让用户能访问到数据库,以避免新的数据插入进来,以及在主从的环境下,关闭主从。 查 看binlog文件,从中找出delete from test.tb1 where id=2
[root@mysql data]# cd /usr/local/mysql/data/
[root@mysql data]# mysqlbinlog -v mysql.000002
显示结果
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#210123 12:13:02 server id 1 end_log_pos 123 CRC32 0x5f0a1eef Start: binlog v 4, server v 5.7.32-log created 210123 12:13:02
# Warning: this binlog is either in use or was not closed properly.
BINLOG '
TqILYA8BAAAAdwAAAHsAAAABAAQANS43LjMyLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAEzgNAAgAEgAEBAQEEgAAXwAEGggAAAAICAgCAAAACgoKKioAEjQA
Ae8eCl8=
'/*!*/;
# at 123
#210123 12:13:02 server id 1 end_log_pos 154 CRC32 0xa5b3c918 Previous-GTIDs
# [empty]
# at 154
#210123 12:13:46 server id 1 end_log_pos 219 CRC32 0x2f9efc20 Anonymous_GTID last_committed=0 sequence_number=1 rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 219
#210123 12:13:46 server id 1 end_log_pos 287 CRC32 0x118532f7 Querythread_id=10 exec_time=0 error_code=0
SET TIMESTAMP=1611375226/*!*/;
SET @@session.pseudo_thread_id=10/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1436549152/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 287
#210123 12:13:46 server id 1 end_log_pos 336 CRC32 0x1a2e6d43 Table_map: `test`.`tb1` mapped to number 108
# at 336
#210123 12:13:46 server id 1 end_log_pos 385 CRC32 0xb1248d2e Delete_rows: table id 108 flags: STMT_END_F
BINLOG '
eqILYBMBAAAAMQAAAFABAAAAAGwAAAAAAAEABHRlc3QAA3RiMQACAw8CPAACQ20uGg==
eqILYCABAAAAMQAAAIEBAAAAAGwAAAAAAAEAAgAC//wCAAAACHpoYW5nc2FuLo0ksQ==
'/*!*/;
### DELETE FROM `test`.`tb1`
### WHERE
### @1=2
### @2='zhangsan'
# at 385
#210123 12:13:46 server id 1 end_log_pos 416 CRC32 0x2e76c931 Xid = 38
COMMIT/*!*/;
# at 416
#210123 12:17:09 server id 1 end_log_pos 481 CRC32 0xad90ccbc Anonymous_GTID last_committed=1 sequence_number=2 rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 481
#210123 12:17:09 server id 1 end_log_pos 549 CRC32 0x9c616e89 Querythread_id=13 exec_time=0 error_code=0
SET TIMESTAMP=1611375429/*!*/;
BEGIN
/*!*/;
# at 549
#210123 12:17:09 server id 1 end_log_pos 598 CRC32 0xe0d21a7e Table_map: `test`.`tb1` mapped to number 108
# at 598
#210123 12:17:09 server id 1 end_log_pos 642 CRC32 0xbc2b5436 Write_rows: table id 108 flags: STMT_END_F
BINLOG '
RaMLYBMBAAAAMQAAAFYCAAAAAGwAAAAAAAEABHRlc3QAA3RiMQACAw8CPAACfhrS4A==
RaMLYB4BAAAALAAAAIICAAAAAGwAAAAAAAEAAgAC//wDAAAAA3RvbTZUK7w=
'/*!*/;
### INSERT INTO `test`.`tb1`
### SET
### @1=3
### @2='tom'
# at 642
#210123 12:17:09 server id 1 end_log_pos 673 CRC32 0x460e93bb Xid = 45
COMMIT/*!*/;
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*/;
从中可以看出delete事件发生position是287,事件结束position是416
恢复流程:直接用bin-log日志将数据库恢复到删除位置287前,然后跳过故障点,再进行恢复下面所有的操作,命令如下 由于之前没有做过全库备份,所以要使用所有binlog日志恢复,所以生产环境中需要很长时间恢复,导出相关binlog文件
[root@mysql data]# mysqlbinlog /usr/local/mysql/data/mysql.000001 > /opt/mysql-bin.001.sql
[root@mysql data]# mysqlbinlog --stop-position=287 /usr/local/mysql/data/mysql.000002 > /opt/287.sql
[root@mysql data]# mysqlbinlog --start-position=416 /usr/local/mysql/data/mysql.000002 > /opt/416.sql
删除test数据库
mysql> drop database test;
Query OK, 1 row affected (0.16 sec)
利用binlog恢复数据
[root@mysql data]# mysql -uroot -p123.com < /opt/mysql-bin.001.sql
[root@mysql data]# mysql -uroot -p123.com < /opt/287.sql
[root@mysql data]# mysql -uroot -p123.com < /opt/416.sql
恢复完成后,我们检查下表的数据是否完整
mysql> select * from test.tb1;
+----+----------+
| id | name |
+----+----------+
| 1 | lisi |
| 2 | zhangsan |
| 3 | tom |
+----+----------+
3 rows in set (0.00 sec)
Ok完整的都恢复过来了 mysqlbinlog 选项示例 常见的选项有以下几个: --start-datetime 从二进制日志中读取指定时间戳或者本地计算机时间之后的日志事件。 --stop-datetime 从二进制日志中读取指定时间戳或者本地计算机时间之前的日志事件。 --start-position
从二进制日志中读取指定position 事件位置作为开始。 --stop-position 从二进制日志中读取指定position 事件位置作为事件截至。
例题:创建库,创建表,插入6条数据,删除两条数据,用二进制备份恢复
insert
insert
delete
insert
insert
delete
insert
insert
开启二进制日志
log_bin=mysql.bin
server_id=1
创建库,表,根据上方条件插入数据,删除数据
mysql> create database test;
mysql> use test;
mysql> create table tab1(id int primary key auto_increment,name varchar(30));
mysql> insert into test.tab1(name) values('tom1');
mysql> insert into test.tab1(name) values('tom2');
mysql> delete from test.tab1 where id=2;
mysql> insert into test.tab1(name) values('tom3');
mysql> insert into test.tab1(name) values('tom4');
mysql> delete from test.tab1 where id=4;
mysql> insert into test.tab1(name) values('tom5');
mysql> insert into test.tab1(name) values('tom6');
select * from test.tab1;
+----+------+
| id | name |
+----+------+
| 1 | q1 |
| 3 | q3 |
| 5 | q5 |
| 6 | q6 |
+----+------+
备份
[root@mysql ~]# mysqlbinlog --stop-position=1184 /usr/local/mysql/data/mysql.000001 > /opt/1184.sql
[root@mysql ~]# mysqlbinlog --start-position=1447 --stop-position=1830 /usr/local/mysql/data/mysql.000001 > /opt/14471830.sql
[root@mysql ~]# mysqlbinlog --start-position=2091 /usr/local/mysql/data/mysql.000001 > /opt/2091.sql
删除库,并还原
mysql> drop database test;
[root@mysql ~]# mysql -uroot -p123.com < /opt/1184.sql
[root@mysql ~]# mysql -uroot -p123.com < /opt/14451830.sql
[root@mysql ~]# mysql -uroot -p123.com < /opt/2091.sql
mysql> select * from tab1;
+----+------+
| id | name |
+----+------+
| 1 | q1 |
| 2 | q2 |
| 3 | q3 |
| 4 | q4 |
| 5 | q5 |
| 6 | q6 |
+----+------+
二、mysqldump介绍
mysqldump是mysql用于备份和数据转移的一个工具。它主要产生一系列的SQL语句,可以封装到文件,该文件包含有所有重建你的数据库所需要的 SQL命令如CREATE DATABASE,CREATE TABLE,INSERT等等。可以用来实现轻量级的快速迁移或恢复数据库。 mysqldump 是将数据表导成 SQL 脚本文件,在不同的 MySQL 版本之间升级时相对比较合适,这也是最常用的备份方法。 mysqldump一般在数据量很小的时候(几个G)可以用于备份。当数据量比较大的情况下,就不建议用mysqldump工具进行备份了。
数据库的导出 导出对象说明:
mysqldump可以针对单个表、多个表、单个数据库、多个数据库、所有数据库进行导出的操作
# mysqldump [options] db_name [tbl_name ...] //导出指定数据库或单个表
# mysqldump [options] -- databases db_name ... //导出多个数据库
# mysqldump [options] --all-databases //导出所有 导出数据库test
# mysqldump -uroot -p --flush-logs test > /opt/test.sql //--flush-logs这个选项就会完整备份的时候
重新开启一个新binlog
单表备份
这里我的表tb1和tb2
[root@mysql ~]# mysqldump -uroot -p123.com test tb1 > /opt/tb1.sql
恢复
[root@mysql ~]# mysql -uroot -p123.com test < /opt/tb1.sql
多表备份
[root@mysql ~]# mysqldump -uroot -p123.com test {tb1,tb2} > /opt/tb12.sql
或
[root@mysql ~]# mysqldump -uroot -p123.com test tb1 tb2 > /opt/tb12.sql
恢复
[root@mysql ~]# mysql -uroot -p123.com test < /opt/tb12.sql
我的库test和test1
单库备份
[root@mysql ~]# mysqldump -uroot -p123.com --database test > /opt/test.sql
恢复
[root@mysql ~]# mysql -uroot -p123.com < /opt/test.sql
注:–databases 也可以用 - B来表示
多库备份
[root@mysql ~]# mysqldump -uroot -p123.com --databases test test1 > /opt/newtest.sql
恢复
[root@mysql ~]# mysql -uroot -p123.com < /opt/newtest.sql
所有库备份
[root@mysql ~]# mysqldump -uroot -p123.com --all-databases > /opt/alldata.sql
恢复
[root@mysql ~]# mysql -uroot -p123.com < /opt/alldata.sql
注:–all-databases 也可以用 -A来表示
如果:information_schema, mysql ,performance_schema,sys这四个库被删掉怎么办?
information_schema : 不允许删除
mysql :可以删除,但是可以根据备份恢复
performance_schema:可以删除备份恢复不回来
sys:可以删除备份恢复不回来
解决办法初始化
[root@mysql ~]# systemctl stop mysqld
[root@mysql ~]# rm -rf /usr/local/mysql/data/*
[root@mysql ~]# mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data
[root@mysql ~]# systemctl start mysqld
修改密码因为密码会变动
在前面我们介绍了mysql的binlog和mysqldump工具,下面我们来学习如何实现mysqldump全库备份+binlog的数据恢复 环境准备与备份还原: 检查开启binlog 先创建一些原始数据
mysql> reset master;
mysql> create database test_db;
mysql> use test_db;
mysql> create table tb1(id int primary key auto_increment,name varchar(20));
mysql> insert into tb1(name) values('tom1');
mysql> insert into tb1(name) values('tom2');
mysql> commit;
mysql> select * from tb1;
+----+------+
| id | name |
+----+------+
| 1 | tom1 |
| 2 | tom2 |
+----+------+
方案:mysqldump全库备份+binlog还原
1、mysqldump备份方案: 每周一凌晨1点全库备份
2、备份步骤
(1) 创建备份目录
[root@mysql ~]# mkdir /opt/mysqlbackup
[root@mysql ~]# mkdir /opt/mysqlbackup/daily
(2)全库备份 这里我们模拟周一的完整备份数据库任务
[root@mysql ~]# mysqldump -uroot -p123.com --flush-logs test_db > /opt/mysqlbackup/test_db_2021_1_24.sql(test_db_`date +%Y%m%d_%H%M%S`)
root@mysql ~]# ls -l /opt/mysqlbackup/
-rw-r--r--. 1 root root 1875 Jan 24 13:14 test_db_2021_1_24.sql
备份mysqldump全库备份之前的binlog日志文(注:生产环境中可能不只一个binlog文件)
[root@mysql ~]# cp /usr//local/mysql/data/mysql.000001 /opt/mysqlbackup/daily/
[root@mysql ~]# mysql -uroot -p123.com -e "purge binary logs to 'mysql.000002'"
模拟下操作失误,将数据修改错误了。
mysql> use test_db;
mysql> delete from tb1 where id=1;
mysql> commit;
mysql> insert into tb1(name) values('tom3');
mysql> commit;
备份自mysqldump之后的binlog日志文件
[root@mysql ~]# cp /usr/local/mysql/data/mysql.000002 /opt/mysqlbackup/daily/
上面的模拟的误操作是删除了id=1的记录
(3)现在我们使用mysqldump的全库备份和binlog来恢复数据。 使 用mysqldump的备份进行全库恢复
[root@mysql ~]# mysql -uroot -p123.com test_db < /opt/mysqlbackup/test_db_2021_1_24.sql(test_db_20210125_115903)
查询一下数据
[root@mysql ~]# mysql -uroot -p123.com -e "select * from test_db.tb1"
+----+------+
| id | name |
+----+------+
| 1 | tom1 |
| 2 | tom2 |
+----+------+
从显示结果可以看到使用mysqldump备份将数据还原到了备份时的状态,刚才删除的数据(id=1)恢复回来了,但备份后产生的数据却丢失了所以还得利用binlog进一步还原 因为删除是在全库备份后发生的,而mysqldump全库备份时使用–flush-logs选项,所以只需要分析全库备份后的binlog即mysql-bin.000002。
mysql> show binary logs;
+--------------+-----------+
| Log_name | File_size |
+--------------+-----------+
| mysql.000002 | 1853 |
+--------------+-----------+
查看mysql-bin.000002中的事件,可以看到有删除事件
mysql> show binlog events in 'mysql.000002';
| mysql.000002 | 219 | Query | 1 | 294 | BEGIN |
| mysql.000002 | 294 | Table_map | 1 | 346 | table_id: 108 (test_db.tb1) |
| mysql.000002 | 346 | Delete_rows | 1 | 391 | table_id: 108 flags: STMT_END_F |
| mysql.000002 | 391 | Xid | 1 | 422 | COMMIT /* xid=45 */
使用mysqlbinlog 命令可以查看备份的binlog文件的详细事件。 恢复流程:我们直接用bin-log日志将数据库恢复到删除位置前,然后跳过故障点,再进行恢复删除后的所有操作。
[root@mysql ~]# mysqlbinlog -v /opt/mysqlbackup/daily/mysql.000002
我们先用mysqlbinlog命令找到delete那条语句的位置
BEGIN
/*!*/;
# at 294
#210125 12:01:05 server id 1 end_log_pos 346 CRC32 0x82db5665 Table_map: `test_db`.`tb1` mapped to number 108
# at 346
#210125 12:01:05 server id 1 end_log_pos 391 CRC32 0xdab66589 Delete_rows: table id 108 flags: STMT_END_F
BINLOG '
gUIOYBMBAAAANAAAAFoBAAAAAGwAAAAAAAEAB3Rlc3RfZGIAA3RiMQACAw8CPAACZVbbgg==
gUIOYCABAAAALQAAAIcBAAAAAGwAAAAAAAEAAgAC//wBAAAABHRvbTGJZbba
'/*!*/;
### DELETE FROM `test_db`.`tb1`
### WHERE
### @1=1
### @2='tom1'
# at 391
#210125 12:01:05 server id 1 end_log_pos 422 CRC32 0x633ca679 Xid = 45
COMMIT/*!*/;
# at 422
#210125 12:01:31 server id 1 end_log_pos 487 CRC32 0x617b3ff4 Anonymous_GTID last_committed=1 sequence_number=2 rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
通过mysqlbinlog命令所显示的结果可以看到误操作delete的开始postion为219,结束position是422。 从二进制日志中读取指定position=294事件位置作为截至,即把数据恢复到delete删除前
[root@mysql ~]# mysqlbinlog --stop-position=294 /opt/mysqlbackup/daily/mysql.000002 | mysql -uroot -p123.com
从二进制日志中读取指定position=422事件位置作为开始,即跳过删除事件,恢复删除事件之后对数据的正常操作
[root@mysql ~]# mysqlbinlog --start-position=422 /opt/mysqlbackup/daily/mysql.000002 | mysql -uroot -p123.com
查看恢复结果:
[root@mysql ~]# mysql -uroot -p123.com -e "select * from test_db.tb1"mysql:
+----+------+
| id | name |
+----+------+
| 1 | tom1 |
| 2 | tom2 |
| 3 | tom3 |
+----+------+
上面这段mysqldump备份和bonlong恢复我用大白话来说一下
1.把之前数据全库备份成一个带时间戳的sql文件并刷新一个mysql.000002,把这个文件cp到/opt/mysqlbackup/daily/下
2.清除一下二进制日志(purge binary logs)mysql.000002
3.模拟删除id1(tom1),插入tom3,cp mysq.000002到/opt/mysqlbackup/daily/下
4.我们库里应该只剩下tom2
5.我们利用之前全库备份的时间戳sql文件把删除的tom1恢复,上面查询显示恢复成功
6.但是我们全库备份之后操作的删除和插入,是记录在mysql.000002里面,因为全库备份之前是没有tom3的,但是有tom1,所以tom1能根据全库备份的时间戳sql文件恢复,tom3就需要
7.通过binlog方式恢复(恢复方式在上面) 恢复之后查询就会看到tom1,Tom2,tom3了
三、全库备份脚本和增量备份脚本
从上面显示可以看出数据恢复到正常状态 生产环境中Mysql数据库的备份是周期性重复的操作,所以通常是要编写脚本实现,通过crond计划任务周期性执行备份脚本 mysqldump备份方案: 周日凌晨1点全库备份 周一到周六凌晨每隔4个小时增量备份一次 设置crontab任务,每天执行备份脚本
# crontab –e
#每个星期日凌晨1:00执行完全备份脚本
0 1 * * 0 /root/mysqlfullbackup.sh >/dev/null 2>&1
#周一到周六每隔4个小时增量备份一次
0 */4 * * 1-6 /root/mysqldailybackup.sh >/dev/null 2>&1
mysqlfullbackup.sh脚本内容:
[root@localhost ~]# cat mysqlfullbackup.sh
#!/bin/sh
# Name:mysqlFullBackup.sh
# 定义数据库目录
mysqlDir=/usr/local/mysql
# 定义用于备份数据库的用户名和密码
user=root
userpwd=123456
dbname=test_db
# 定义备份目录
databackupdir=/opt/mysqlbackup
[ ! -d $databackupdir ] && mkdir $databackupdir
# 定义邮件正文文件
emailfile=$databackupdir/email.txt
# 定义邮件地址
email=root@localhost.localdomain
# 定义备份日志文件
logfile=$databackupdir/mysqlbackup.log
DATE=`date -I`
echo "" > $emailfile
echo $(date +"%y-%m-%d %H:%M:%S") >> $emailfile
cd $databackupdir
# 定义备份文件名
dumpfile=mysql_$DATE.sql
gzdumpfile=mysql_$DATE.sql.tar.gz
# 使用mysqldump备份数据库,请根据具体情况设置参数
$mysqlDir/bin/mysqldump -u$user -p$userpwd --flush-logs -x $dbname > $dumpfile
//-x--lock-all-tables
# 压缩备份文件
if [ $? -eq 0 ]; then
tar czf $gzdumpfile $dumpfile >> $emailfile 2>&1
echo "BackupFileName:$gzdumpfile" >> $emailfile
echo "DataBase Backup Success!" >> $emailfile
rm -f $dumpfile
else
echo "DataBase Backup Fail!" >> $emailfile
fi
# 写日志文件
echo "--------------------------------------------------------" >> $logfile
cat $emailfile >> $logfile
# 发送邮件通知
cat $emailfile | mail -s "MySQL Backup" $email
简化
#!/bin/bash
mysqldir=/usr/local/mysql
user=root
userpwd=123.com
dbname=test
databackupdir=/opt/mysqlbackup
[ ! -d $databackupdir ] && mkdir $databackupdir
logfile=$databackupdir/mysqlbackup.log
date=`date -I`
echo " " > $logfile
echo $(date +"%y-%m-%d %H:%M:%S") >> $logfile
cd $databackupdir
dumpfile=mysql_$date.sql
gzdumpfile=mysql_$date.sql.tar.gz
$mysqldir/bin/mysqldump -u$user -p$userpwd -F -x $dbname > $dumpfile
if [ $? -eq 0 ]; then
tar czf $gzdumpfile $dumpfile >> $logfile 2>&1
echo "backupfilename:$gzdumpfile" >> $logfile
echo "数据库备份成功!" >> $logfile
rm -f $dumpfile
else
echo "数据库备份失败!" $logfile
fi
增量备份(incremental backup)是备份的一个类型,是指在一次全备份或上一次增量备份后,以后每次的备份只需备份与前一次相比增加或者被修改的文件。
mysqldailybackup.sh脚本内容:
[root@localhost ~]# cat mysqldailybackup.sh
#!/bin/sh
# Name:mysqlDailyBackup.sh
# 定义数据库目录和数据目录
mysqldir=/usr/local/mysql
datadir=$mysqldir/data
# 定义用于备份数据库的用户名和密码
user=root
userpwd=123456
# 定义备份目录,每日备份文件备份到$dataBackupDir/daily
databackupdir=/opt/mysqlbackup
dailybackupdir=$databackupdir/daily
[ ! -d $dailybackupdir ] && mkdir -p $databackupdir/daily
# 定义邮件正文文件
emailfile=$databackupdir/email.txt
# 定义邮件地址
email=root@localhost.localdomain
# 定义日志文件
logfile=$databackupdir/mysqlbackup.log
echo "" > $emailfile
echo $(date +"%y-%m-%d %H:%M:%S") >> $emailfile
#
# 刷新日志,使数据库使用新的二进制日志文件
$mysqldir/bin/mysqladmin -u$user -p$userpwd flush-logs
cd $datadir
# 得到二进制日志列表
filelist=`cat mysql-bin.index`
icounter=0
for file in $filelist
do
icounter=`expr $icounter + 1` // = let icounter++
done
nextnum=0
ifile=0
for file in $filelist
do
binlogname=`basename $file`
nextnum=`expr $nextnum + 1`
# 跳过最后一个二进制日志(数据库当前使用的二进制日志文件)
if [ $nextnum -eq $icounter ]; then
echo "Skip lastest!" > /dev/null
else
dest=$dailybackupdir/$binlogname
# 跳过已经备份的二进制日志文件
if [ -e $dest ]; then
echo "Skip exist $binlogname!" > /dev/null
else
# 备份日志文件到备份目录
cp $binlogname $dailybackupdir
if [ $? -eq 0 ]; then
ifile=`expr $ifile + 1`
echo "$binlogname backup success!" >> $emailfile
fi
fi
fi
done
if [ $ifile -eq 0 ];then
echo "No Binlog Backup!" >> $emailfile
else
echo "Backup $ifile File(s)." >> $emailfile
echo "Backup MySQL Binlog OK!" >> $emailfile
fi
# 发送邮件通知
cat $emailfile | mail -s "MySQL Backup" $email
# 写日志文件
echo "--------------------------------------------------------" >> $logfile
cat $emailfile >> $logfile
简化
#!/bin/bash
mysqldir=/usr/local/mysql
datadir=$mysqldir/data
user=root
userpwd=123.com
databackupdir=/opt/mysqlbackup
dailybackupdir=$databackupdir/daily
[ ! -d $dailybackupdir ] && mkdir -p $databackupdir/daily
logfile=$databackupdir/mysqlbackup.log
echo " " > $logfile
echo $(date +"%y-%m-%d %H:%M:%S") >> $logfile
$mysqldir/bin/mysqladmin -u$user -p$userpwd flush-logs
cd $datadir
filelist=`cat mysql.index`
icounter=0
for file in $filelist
do
icounter=`expr $icounter + 1`
done
nextnum=0
ifile=0
for file in $filelist
do
binlogname=`basename $file`
nextnum=`expr $nextnum + 1`
if [ $nextnum -eq $icounter ]; then
echo "Skip lastest!" > /dev/null
else
dest=$dailybackupdir/$binlogname
if [ -e $dest ]; then
echo "Skip exist $binlogname!" > /dev/null
else
cp $binlogname $dailybackupdir
if [ $? -eq 0 ]; then
ifile=`expr $ifile + 1`
echo "$binlogname backup success!" >> $logfile
fi
fi
fi
done
if [ $ifile -eq 0 ];then
echo "No Binlog Backup!" >> $logfile
else
echo "Backup $ifile File(s)." >> $logfile
echo "backup MySQL Binlog OK!" >> $logfile
fi
四、使用xtrabackup进行MySQL数据库备份
前面介绍mysqldump备份方式是采用逻辑备份,其最大的缺陷就是备份和恢复速度都慢,对于一个小于50G的数据库而言,这个速度还是能接受的,但如果数据库非常大,那再使用mysqldump备份就不太适合了。
这时就需要一种好用又高效的工具,xtrabackup就是其中一款,号称免费版的InnoDB HotBackup。 Xtrabackup实现是物理备份,而且是物理热备 目前主流的有两个工具可以实现物理热备:ibbackup和xtrabackup;ibbackup是商业软件,需要授权,非常昂贵。而xtrabackup功能比ibbackup还要强大,但却是开源的。因此我们这里就来介绍xtrabackup的使用。 Xtrabackup提供了两种命令行工具: xtrabackup:专用于备份InnoDB和XtraDB引擎的数据; innobackupex:这是一个perl脚本,在执行过程中会调用xtrabackup命令,这样用该命令即可以实现备份InnoDB,也可以备份MyISAM引擎的对象
Xtrabackup是由percona提供的mysql数据库备份工具。
特点:
(1)备份过程快速、可靠;
(2)备份过程不会打断正在执行的事务;
(3)能够基于压缩等功能节约磁盘空间和流量;
(4)自动实现备份检验;
(5)还原速度快。
官方链接地址:http://www.percona.com/software/percona-xtrabackup;
可以下载源码编译安装,也可以下载适合的RPM包或使用yum进行安装或者下载二进制源码包。 安装xtrabackup
1)下载xtrabackup
wget https://downloads.percona.com/downloads/Percona-XtraBackup-2.4/Percona-XtraBackup-2.4.15/binary/tarball/percona-xtrabackup-2.4.15-Linux-x86_64.libgcrypt153.tar.gz
注:这个需要根据自己的libgcrypt版本下载
[root@mysql ~]# rpm -qa |grep libgcrypt //这个是我的
libgcrypt-1.5.3-14.el7.x86_64
2)解压
[root@mysql ~]# tar zxf percona-xtrabackup-2.4.15-Linux-x86_64.libgcrypt153.tar.gz
3)进入解压目录
[root@mysql ~]# cd percona-xtrabackup-2.4.15-Linux-x86_64/
4)复制bin下的所有程序到/usr/bin
[root@mysql ~]# cp percona-xtrabackup-2.4.15-Linux-x86_64/bin/* /usr/bin/
Xtrabackup中主要包含两个工具:
**xtrabackup:**是用于热备份innodb, xtradb表中数据的工具,支持在线热备份,可以在不加锁的情况下备份Innodb数据表,不过此工具不能操作Myisam引擎表;
**innobackupex:**是将xtrabackup进行封装的perl脚本,能同时处理Innodb和Myisam,但在处理Myisam时需要加一个读锁。 由于操作Myisam时需要加读锁,这会堵塞线上服务的写操作,而Innodb没有这样的限制,所以数据库中Innodb表类型所占的比例越大,则越有利。
4)安装相关插件
[root@mysql ~]# yum -y install perl-DBI perl-DBD-MySQL perl-Time-HiRes perl-IO-Socket-SSL perl-TermReadKey.x86_64 perl-Digest-MD5
5)下载percona-toolkit并安装
wget https://downloads.percona.com/downloads/percona-toolkit/3.3.0/binary/redhat/7/x86_64/percona-toolkit-3.3.0-1.el7.x86_64.rpm
[root@mysql ~]# rpm -ivh percona-toolkit-3.3.0-1.el7.x86_64.rpm
下面就可以启动备份了
方案一 xtrabackup完全备份+binlog增量备份
1.完全备份和增量备份
开启二进制日志并重启
[root@mysql ~]# vim /etc/my.cnf
log-bin=mysql-bin
server-id=1
创建库,创建表,插入数据
mysql> create database test;
mysql> use test
mysql> create table xtr ( id int primary key auto_increment, name varchar(20) );
mysql> insert into xtr(name) values('xtr1'),('xtr2');
mysql> select * from xtr;
+----+------+
| id | name |
+----+------+
| 1 | xtr1 |
| 2 | xtr2 |
+----+------+
1.创建备份目录
[root@mysql ~]# mkdir -p /opt/mysqlbackup/{full,inc}
full:全备存放的目录;
inc:增量备份存放的目录
1)完全备份
基本语法:
# innobackupex --user=DBUSER --password=DBUSERPASS /path/to/BACKUP-DIR/
执行下面的命令进行完全备份:
[root@mysql ~]# innobackupex --default-file=/etc/my.cnf -S /tmp/mysql.sock --user=root --password=123.com /opt/mysqlbackup/full/
注: --defaults-file=/etc/my.cnf 指定mysql的配置文件my.cfg,如果指定则必须是第一个参数。
/path/to/BACKUP-DIR/指定备份所存放的目标目录,备份过程会创建一个以当时备份时间命名的目录存放备份文件。
这个版本一定要加-S也就是sock 如果不加 他会提示找不到,所以要写上sock的位置。
出现如下提示。表示成功
200113 09:49:36 Finished backing up non-InnoDB tables and files
200113 09:49:36 Executing FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS...
xtrabackup: The latest check point (for incremental): '67343410'
xtrabackup: Stopping log copying thread.
.200113 09:49:36 >> log scanned up to (67343419)
200113 09:49:37 Executing UNLOCK TABLES
200113 09:49:37 All tables unlocked
200113 09:49:37 [00] Copying ib_buffer_pool to /opt/mysqlbackup/full/2020-01-
13_09-49-22/ib_buffer_pool
200113 09:49:37 [00] ...done
200113 09:49:37 Backup created in directory '/opt/mysqlbackup/full/2020-01-13_09-
49-22'
200113 09:49:37 [00] Writing backup-my.cnf
200113 09:49:37 [00] ...done
200113 09:49:37 [00] Writing xtrabackup_info
200113 09:49:37 [00] ...done
xtrabackup: Transaction log of lsn (67343410) to (67343419) was copied.
200113 09:49:37 completed OK!
备份后的文件: 在备份的同时,备份数据会在备份目录下创建一个以当前日期时间为名字的目录存放备份文件:
[root@mysql ~]# cd /opt/mysqlbackup/full/
[root@mysql full]# ll
total 0
drwxr-x---. 6 root root 235 Jan 29 12:42 2021-01-29_12-42-33
[root@mysql full]# ll 2021-01-29_12-42-33/
total 12340
-rw-r-----. 1 root root 487 Jan 29 12:42 backup-my.cnf
-rw-r-----. 1 root root 360 Jan 29 12:42 ib_buffer_pool
-rw-r-----. 1 root root 12582912 Jan 29 12:42 ibdata1
drwxr-x---. 2 root root 4096 Jan 29 12:42 mysql
drwxr-x---. 2 root root 8192 Jan 29 12:42 performance_schema
drwxr-x---. 2 root root 8192 Jan 29 12:42 sys
drwxr-x---. 2 root root 50 Jan 29 12:42 test
-rw-r-----. 1 root root 21 Jan 29 12:42 xtrabackup_binlog_info
-rw-r-----. 1 root root 135 Jan 29 12:42 xtrabackup_checkpoints
-rw-r-----. 1 root root 526 Jan 29 12:42 xtrabackup_info
-rw-r-----. 1 root root 2560 Jan 29 12:42 xtrabackup_logfile
各文件说明:
(1)xtrabackup_checkpoints ——备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息; 每个InnoDB页(通常为16k大小)都会包含一个日志序列号,即LSN。LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的。
(2)xtrabackup_binlog_info —— mysql服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置。
(3)xtrabackup_binlog_pos_innodb ——二进制日志文件及用于InnoDB或XtraDB表的二进制日志文件的当前position。
(4)xtrabackup_binary ——备份中用到的xtrabackup的可执行文件;
(5)backup-my.cnf ——备份命令用到的配置选项信息;
在使用innobackupex进行备份时,还可以使用–no-timestamp选项来阻止命令自动创建一个以时间命名的目录;如此一来,innobackupex命令将会创建一个BACKUP-DIR目录来存储备份数据
注意:相关选项说明:
--user指定连接数据库的用户名,
--password指定连接数据库的密码,
--defaults-file指定数据库的配置文件,innobackupex要从其中获取datadir等信息;
--database指定要备份的数据库,这里指定的数据库只对MyISAM表有效,对于InnoDB 数据来说都是全备(所有数据库中的InnoDB数据都进行了备份,不是只备份指定的数据库,恢复时也一样);
/opt/mysqlbackup/full是备份文件的存放位置。
注意:备份数据库的用户需要具有相应权限,如果要使用一个最小权限的用户进行备份,则可基于如下命令创建此类用户:现实工作中root权限太大
创建用户
mysql> create user 'bkpuser'@'localhost' identified by '123';
收回权限
mysql> revoke all privileges,grant option from 'bkpuser'@'localhost';
给予权限
mysql> grant reload,lock tables,replication client,process on *.* to 'bkpuser'@'localhost';
mysql> flush privileges;
给予的四个权限解释
reload : 重新刷新表,日志,权限
lock tables:锁表
process :查看纯文本,执行一些查询语句
replication client :询问主从的server在什么地方
至此全备完全成功,然后向mysql某个库插入几条数据,然后进行增量备份 对完全备份的后数据库更改进行二进制日志增量备份:
查看完全备份时binlog日志位置(position) :
因为在数据特别多的情况下去找他的位置不太好找,所以用下面的命令查看就可以了
[root@mysql ~]# cat /opt/mysqlbackup/full/2021-01-29_12-42-33/xtrabackup_binlog_info
mysql-bin.000001 796
模拟数据库修改:
mysql> select * from xtr;
+----+------+
| id | name |
+----+------+
| 1 | xtr1 |
| 2 | xtr2 |
+----+------+
2 rows in set (0.00 sec)
mysql> insert into xtr(name) values('xtr3');
Query OK, 1 row affected (0.01 sec)
2)增量备份二进制文件:
[root@mysql data]# mysqlbinlog --start-position=796 /usr/local/mysql/data/mysql-bin.000001 > /opt/mysqlbackup/inc/`date +%F`.sql
2.还原完全备份和增量备份
1)模拟数据库损坏:
我这里直接使用删除数据目录文件来模拟损坏。
[root@mysql ~]# rm -rf /usr/local/mysql/data/*
2)还原完全备份:
(1)准备(prepare)一个完全备份 一般情况下,在备份完成后,数据尚且不能用于恢复操作,
因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务。因此,此时数据文件仍处理不一致状态。“准备”的主要作用正是通过回滚未提交的事务及同步已经提交的事务至数据文件也使得数据文件处于一致性状态。 在准备(prepare)过程结束后,InnoDB表数据已经前滚到整个备份结束的点,而不是回滚到xtrabackup刚开始时的点。 innobakupex命令的–apply-log选项可用于实现上述功能。
如下面的命令: --apply-log指明是将日志应用到数据文件上,完成之后将备份文件中的数据恢复到数据库中:
[root@mysql ~]# innobackupex --apply-log /opt/mysqlbackup/full/2021-01-29_12-42-33/
注:/opt/mysqlbackup/full/2021-01-29_12-42-33/备份文件所在目录名称 如果执行正确,其最后输出的几行信息通常如下:
InnoDB: Starting crash recovery.
InnoDB: Removed temporary tablespace data file: "ibtmp1"
InnoDB: Creating shared tablespace for temporary tables
InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full;
Please wait ...
InnoDB: File './ibtmp1' size is now 12 MB.
InnoDB: 96 redo rollback segment(s) found. 1 redo rollback segment(s) are active.
InnoDB: 32 non-redo rollback segment(s) are active.
InnoDB: Waiting for purge to start
InnoDB: 5.7.19 started; log sequence number 67343893
xtrabackup: starting shutdown with innodb_fast_shutdown = 1
InnoDB: FTS optimize thread exiting.
InnoDB: Starting shutdown...
InnoDB: Shutdown completed; log sequence number 67343912
200113 10:10:23 completed OK!
在实现“准备”的过程中,innobackupex通常还可以使用–use-memory选项来指定其可以使用的内存的大小,默认通常为100M。如果有足够的内存可用,可以多划分一些内存给prepare的过程,以提高其完成速度。innobackupex命令的–copy-back选项用于执行恢复操作,其通过复制所有数据相关的文件至mysql服务器DATADIR目录中来执行恢复过程。innobackupex通过backup-my.cnf来获取DATADIR目录的相关信息。
3)还原数据库语法:
[root@mysql data]# innobackupex --copy-back /opt/mysqlbackup/full/2021-01-29_12-42-33/
这里的–copy-back指明是进行数据恢复。数据恢复完成之后,需要修改相关文件的权限mysql数据库才能正常启动。 如果执行正确,其输出信息的最后几行通常如下:
200113 10:11:24 [01] Copying ./performance_schema/global_status.frm to
/usr/local/mysql/data/performance_schema/global_status.frm
200113 10:11:24 [01] ...done
200113 10:11:24 [01] Copying ./performance_schema/session_status.frm to
/usr/local/mysql/data/performance_schema/session_status.frm
200113 10:11:24 [01] ...done
200113 10:11:24 [01] Copying ./test1/db.opt to /usr/local/mysql/data/test1/db.opt
200113 10:11:24 [01] ...done
200113 10:11:24 [01] Copying ./ib_buffer_pool to
/usr/local/mysql/data/ib_buffer_pool
200113 10:11:24 [01] ...done
200113 10:11:24 [01] Copying ./xtrabackup_info to
/usr/local/mysql/data/xtrabackup_info
200113 10:11:24 [01] ...done
200113 10:11:24 [01] Copying ./ibtmp1 to /usr/local/mysql/data/ibtmp1
200113 10:11:24 [01] ...done
200113 10:11:24 completed OK!
请确保如上信息的最行一行出现“completed OK!”。
修改还原后的数据目录权限:
[root@mysql data]# ll /usr/local/mysql/data/
total 122924
-rw-r-----. 1 root root 360 Jan 29 13:35 ib_buffer_pool
-rw-r-----. 1 root root 12582912 Jan 29 13:35 ibdata1
-rw-r-----. 1 root root 50331648 Jan 29 13:35 ib_logfile0
-rw-r-----. 1 root root 50331648 Jan 29 13:35 ib_logfile1
-rw-r-----. 1 root root 12582912 Jan 29 13:35 ibtmp1
drwxr-x---. 2 root root 4096 Jan 29 13:35 mysql
drwxr-x---. 2 root root 8192 Jan 29 13:35 performance_schema
drwxr-x---. 2 root root 8192 Jan 29 13:35 sys
drwxr-x---. 2 root root 50 Jan 29 13:35 test
-rw-r-----. 1 root root 21 Jan 29 13:35 xtrabackup_binlog_pos_innodb
-rw-r-----. 1 root root 526 Jan 29 13:35 xtrabackup_info
-rw-r-----. 1 root root 1 Jan 29 13:35 xtrabackup_master_key_id
当数据恢复至DATADIR目录以后,还需要确保所有数据文件的属主和属组均为正确的用户,如mysql,否则,在启动mysqld之前还需要事先修改数据文件的属主和属组。如:
[root@mysql data]# chown -R mysql:mysql /usr/local/mysql/data/
必须重启MySQL:
[root@mysql data]# systemctl restart mysqld
验证还原后的数据:
mysql> select * from xtr;
+----+------+
| id | name |
+----+------+
| 1 | xtr1 |
| 2 | xtr2 |
+----+------+
2 rows in set (0.00 sec)
还原增量备份
为了防止还原时产生大量的二进制日志,在还原时可临时关闭二进制日志后再还原:
mysql> set sql_log_bin=0;
mysql> source /opt/mysqlbackup/inc/2021-01-29.sql;
或者在命令行:
mysql –uroot –p < /opt/mysqlbackup/inc/2021-01-29.sql
mysqlbinlog /opt/mysqlbackup/inc/2021-01-29.sql | mysql –uroot -p
重新启动二进制日志并验证还原数据:
mysql> set sql_log_bin=1;
验证数据是否恢复回来
mysql> select * from xtr;
+----+------+
| id | name |
+----+------+
| 1 | xtr1 |
| 2 | xtr2 |
| 3 | xtr3 |
+----+------+
方案二 xtrabackup完全备份+xtrabacup增量备份
前面我们进行增量备份时,使用的还是老方法:备份二进制日志。其实xtrabackup还支持进行增量备份。 先介绍下xtrabackup的备份原理 在InnoDB内部会维护一个redo日志文件,我们也可以叫做事务日志文件(transaction log,事务日志)。事务日志会存储每一个InnoDB表数据的记录修改。当InnoDB启动时,InnoDB会检查数据文件和事务日志,并执行两个步骤:它应用已经提交的事务日志到数据文件,并将修改过但没有提交的数据进行回滚操作。 xtrabackup在启动时会记住log sequence number(LSN),并且复制所有的数据文件。复制过程需要一些时间,所以这期间如果数据文件有改动,那么将会使数据库处于一个不同的时间点。这时,xtrabackup会运行一个后台进程,用于监视事务日志,并从事务日志复制最新的修改。xtrabackup必须持续的做这个操作,是因为事务日志是会轮转重复的写入,并且事务日志可以被重用。所以xtrabackup自启动开始,就不停的将事务日志中每个数据文件的修改都记录下来。这就是xtrabackup的备份过程。
所以每个InnoDB的页面都会包含一个LSN信息,每当相关的数据发生改变,相关的页面的LSN就会自动增长。这正是InnoDB表可以进行增量备份的基础。 xtraBackup基于InnoDB的crash-recovery功能。它会复制innodb的data file,由于不锁表,复制出来的数据是不一致的,在恢复的时候使用crash-recovery,使得数据恢复一致。当InnoDB启动的时候,它会先去检查data file和transaction log,并且会做二步操作:
1.It applies committed transaction logentries to the data files
2.it performs an undo operation on anytransactions that modified data but did not commit.
所以在prepare过程中,XtraBackup使用复制到的transactions log对备份出来的innodb data file进行crash recovery。
测试环境准备
还是用刚才的环境
mysql> select * from xtr;
+----+------+
| id | name |
+----+------+
| 1 | xtr1 |
| 2 | xtr2 |
| 3 | xtr3 |
+----+------+
1.xtrabacup进行完全备份和增量备份
备份命令:
这里用另一个用户做一下
[root@mysql ~]# xtrabackup --defaults-file=/etc/my.cnf -S /tmp/mysql.sock --user=bkpuser --password=123 --prot=3306 --backup --target-dir=/opt/mysqlbackup/full/full_incre_$(date +%Y%m%d_%H%M%S)
部分显示信息如下所示:
–defaults-file指定数据库的配置文件,如果使用该参数必须做为第一个参数;
–user指定连接数据库的用户名;
–password指定连接数据库的密码;
–port指定连接数据库的端口号;
–backup 实施备份到target-dir;
–target-dir=name 备份文件的存放目录路径。innobackupex要从其中获取datadir等信息;
–database指定要备份的数据库,这里指定的数据库只对MyISAM表和InnoDB表的表结构有效,对于InnoDB 数据来说都是全备(所有数据库中的InnoDB数据都进行了备份,不是只备份指定的数据库,恢复时也一样);
**/opt/mysqlbackup/full/**是备份文件的存放位置。
查看完全备份文件
[root@mysql ~]# ls /opt/mysqlbackup/full/ -l
drwxr-x---. 6 root root 235 Jan 29 14:06 full_incre_20210129_140635
xtrabackup进行增量备份 先录入些数据,实现第一次增量数据:
mysql> select * from xtr;
+----+------+
| id | name |
+----+------+
| 1 | xtr1 |
| 2 | xtr2 |
| 3 | xtr3 |
+----+------+
3 rows in set (0.00 sec)
mysql> insert into xtr(name) values('xtr4');
再进行增量备份1
备份命令:
[root@mysql full]# xtrabackup --defaults-file=/etc/my.cnf -S /tmp/mysql.sock --user=bkpuser --password=123 --prot=3306 --backup --target-dir=/opt/mysqlbackup/inc/inc_incre_$(date +%y%m%d_%H%M%S) --incremental-basedir=/opt/mysqlbackup/full/full_incre_20210129_140635/
部分显示信息如下所示:
–incremental-basedir指定上次完整备份或者增量备份文件的位置(即如果是第一次增量备份则指向完全备份所在目录,在执行过增量备份之后再一次进行增量备份时,就是基于谁去做增量备份
–incremental-basedir应该指向上一次的增量备份所在的目录)。
查看增量备份文件:
[root@mysql full]# ls -l /opt/mysqlbackup/inc/
drwxr-x---. 6 root root 261 Jan 29 14:15 inc_incre_20210129_141533
注:这里的增量备份其实只针对的是InnoDB,对于MyISAM来说,还是完整备份。
向表中再插入几行数据,继续第二次增量备份
mysql> select * from xtr;
+----+------+
| id | name |
+----+------+
| 1 | xtr1 |
| 2 | xtr2 |
| 3 | xtr3 |
| 4 | xtr4 |
+----+------+
4 rows in set (0.00 sec)
mysql> insert into xtr(name) values('xtr5');
进行第二次增量备份
备份命令:
[root@mysql ~]# xtrabackup --defaults-file=/etc/my.cnf -S /tmp/mysql.sock --user=bkpuser --password=123 --prot=3306 --backup --target-dir=/opt/mysqlbackup/inc/inc_incre_$(date +%y%m%d_%H%M%S) --incremental-basedir=/opt/mysqlbackup/inc/inc_incre_20210129_141533/
部分显示信息如下所示:
注:第二次增量备份**–incremental-basedir**指向上一次增量备份文件的位置。
查看增量备份文件
[root@mysql ~]# ls -l /opt/mysqlbackup/inc/
drwxr-x---. 6 root root 261 Jan 29 14:15 inc_incre_20210129_141533
drwxr-x---. 6 root root 261 Jan 29 14:24 inc_incre_20210129_142409
2.xtrabacup进行完全恢复和增量恢复
为了验证比对,删除表里面的数据
mysql> delete from xtr;
Query OK, 5 rows affected (0.01 sec)
完整备份恢复: 在进行恢复前,如果完整备份在远程主机上,首先将完整备份复制到本地主机上,如果是tar包,则需要先解包,解包命令为:tar –izxf xxx.tar,这里必须使用-i参数(忽略存档中的 0 字节块(通常意味着文件结束))。
开始全备份恢复 命令如下:
[root@mysql ~]# xtrabackup --defaults-file=/etc/my.cnf --prepare --user=blpuser --password=123 --apply-log-only --target-dir=/opt/mysqlbackup/full/full_incre_20210129_140635/
恢复到第一次增量
增量备份恢复的步骤和完整备份恢复的步骤基本一致,只是应用日志的过程稍有不同。增量备份恢复时,是先将所有的增量备份挨个应用到完整备份的数据文件中,然后再将完整备份中的数据恢复到数据库中。
[root@mysql ~]# xtrabackup --defaults-file=/etc/my.cnf --prepare --user=blpuser --password=123 --apply-log-only --target-dir=/opt/mysqlbackup/full/full_incre_20210129_140635/ --incremental-dir=/opt/mysqlbackup/inc/inc_incre_20210129_141533/
恢复到第二次增量备份前面:
恢复命令:
[root@mysql ~]# xtrabackup --defaults-file=/etc/my.cnf --prepare --user=blpuser --password=123 --apply-log-only --target-dir=/opt/mysqlbackup/full/full_incre_20210129_140635/ --incremental-dir=/opt/mysqlbackup/inc/inc_incre_20210129_142409/
恢复整个库 恢复命令:
[root@mysql ~]# xtrabackup --defaults-file=/etc/my.cnf --prepare --user=blpuser --password=123 --target-dir=/opt/mysqlbackup/full/full_incre_20210129_140635/
然后停止mysql数据库:
[root@localhost ~]# systemctl stop mysqld
开始rsync数据文件:
[root@mysql ~]# cd /opt/mysqlbackup/full/full_incre_20210129_140635/
[root@mysql full_incre_20210129_140635]# rsync -rvt --exclude 'xtrabackup_logfile' --exclude 'xtrabackup_checkpoints' /opt/mysqlbackup/full/full_incre_20210129_140635/ /usr/local/mysql/data/
当数据恢复至DATADIR目录以后,还需要确保所有数据文件的属主和属组均为正确的用户,如mysql,否则,在启动mysqld之前还需要事先修改数据文件的属主和属组。
授予mysql访问权限:
[root@mysql ~]# chown -R mysql:mysql /usr/local/mysql/data/
启动mysql服务:
[root@mysql ~]# systemctl start mysqld
验证 登录mysql,看到以前在备份之后删除的数据已经通过2次增量备份恢复过来了,如下所示:
mysql> select * from xtr;
+----+------+
| id | name |
+----+------+
| 1 | xtr1 |
| 2 | xtr2 |
| 3 | xtr3 |
| 4 | xtr4 |
| 5 | xtr5 |
+----+------+
5 rows in set (0.00 sec)
方案三 innobackupex全库备份+innobackupex增量备份
测试环境准备 还是上个方案的环境
mysql> select * from xtr;
+----+------+
| id | name |
+----+------+
| 1 | xtr1 |
| 2 | xtr2 |
| 3 | xtr3 |
| 4 | xtr4 |
| 5 | xtr5 |
+----+------+
1.innobackupex先做完全备份和增量备份
命令如下:
[root@mysql ~]# innobackupex --defaults-file=/etc/my.cnf -S /tmp/mysql.sock --user=bkpuser --password=123 --no-timestamp /opt/mysqlbackup/full/full_incre_$(date +%Y%m%d_%H%M%S)
查看完全备份文件
[root@mysql ~]# ll /opt/mysqlbackup/full/
drwxr-x---. 6 root root 235 Jan 29 15:12 full_incre_20210129_151158
innobackupex做增量备份
做第一次增量备份 先录入增量数据
mysql> insert into xtr(name) values('xtr6');
Query OK, 1 row affected (0.00 sec)
mysql> select * from xtr;
+----+------+
| id | name |
+----+------+
| 1 | xtr1 |
| 2 | xtr2 |
| 3 | xtr3 |
| 4 | xtr4 |
| 5 | xtr5 |
| 6 | xtr6 |
+----+------+
6 rows in set (0.00 sec)
再进行增量备份,命令如下:
[root@mysql full]# innobackupex --user=bkpuser --password=123 -S /tmp/mysql.sock --no-timestamp --incremental /opt/mysqlbackup/inc/incre_$(date +%Y%m%d_%H%M%S) --incremental-basedir=/opt/mysqlbackup/full/full_incre_20210129_151158/
查看增量备份文件
[root@mysql ~]# ll /opt/mysqlbackup/inc/
drwxr-x---. 6 root root 261 Jan 29 15:52 incre_20210129_155216
基于全备和第一个增量备份来做第二次增量备份 先录入增量数据录入
mysql> insert into xtr(name) values('xtr7');
Query OK, 1 row affected (0.00 sec)
mysql> select * from xtr;
+----+------+
| id | name |
+----+------+
| 1 | xtr1 |
| 2 | xtr2 |
| 3 | xtr3 |
| 4 | xtr4 |
| 5 | xtr5 |
| 6 | xtr6 |
| 7 | xtr7 |
+----+------+
7 rows in set (0.01 sec)
开始进行第二次增量备份,备份命令:
[root@mysql ~]# innobackupex --user=bkpuser --password=123 -S /tmp/mysql.sock --no-timestamp --incremental /opt/mysqlbackup/inc/incre_$(date +%Y%m%d_%H%M%S) --incremental-basedir=/opt/mysqlbackup/inc/incre_20210129_155216/
查看增量备份文件
[root@mysql ~]# ll /opt/mysqlbackup/inc/
drwxr-x---. 6 root root 261 Jan 29 15:52 incre_20210129_155216
drwxr-x---. 6 root root 261 Jan 29 15:55 incre_20210129_155545
2.innobackupex做完全恢复和增量恢复
先删除两次增量数据,用来查看验证恢复结果
mysql> delete from xtr;
Query OK, 7 rows affected (0.00 sec)
开始做恢复,恢复全备份 命令如下:
[root@mysql ~]# innobackupex --apply-log --redo-only /opt/mysqlbackup/full/full_incre_20210129_151158/
–redo-only 用于准备增量备份内容把数据合并到全备份目录,配合incremental-dir 增量备份目录使用
基于全备份进行第一次增量备份的恢复 命令如下:
[root@mysql ~]# innobackupex --apply-log --redo-only /opt/mysqlbackup/full/full_incre_20210129_151158/ --incremental-dir=/opt/mysqlbackup/inc/incre_20210129_155216/
基于全备份和第一次增量备份,恢复第二次增量备份 命令如下:
[root@mysql ~]# innobackupex --apply-log --redo-only /opt/mysqlbackup/full/full_incre_20210129_151158/ --incremental-dir=/opt/mysqlbackup/inc/incre_20210129_155545/
恢复整个数据库 停止数据库
[root@mysql ~]# systemctl stop mysqld
清空数据目录下所有文件
[root@mysql ~]# rm -rf /usr/local/mysql/data/*
将恢复好的数据按照配置文件的需求拷贝到相应目录
[root@mysql ~]# innobackupex --default-file=/etc/my.cnf --user=bkpuser --password=123 --copy-back /opt/mysqlbackup/full/full_incre_20210129_151158/
当数据恢复至DATADIR目录以后,还需要确保所有数据文件的属主和属组均为正确的用户,如mysql,否则,在启动mysqld之前还需要事先修改数据文件的属主和属组。
赋予mysql账号权限
[root@mysql data]# chown -R mysql:mysql /usr/local/mysql/data/
启动mysql服务
[root@mysql data]# systemctl start mysqld
登录mysql界面,查看数据是否已经恢复,如下所示:
mysql> use test;
mysql> select * from xtr;
+----+------+
| id | name |
+----+------+
| 1 | xtr1 |
| 2 | xtr2 |
| 3 | xtr3 |
| 4 | xtr4 |
| 5 | xtr5 |
| 6 | xtr6 |
| 7 | xtr7 |
+----+------+
7 rows in set (0.00 sec)
备份压缩(打成包)
附:Xtrabackup的“流”及“备份压缩”功能 Xtrabackup对备份的数据文件支持“流”功能,即可以将备份的数据通过STDOUT传输给tar程序进行归档,而不是默认的直接保存至某备份目录中。要使用此功能,仅需要使用–stream选项即可。如:
[root@mysql ~]# innobackupex --user=bkpuser --password=123 -S /tmp/mysql.sock --stream=tar /opt/mysqlbackup/full/ | gzip > /opt/mysqlbackup/full/full_`date +%Y%m%d_%H%M%s`.tar.gz
查看
[root@mysql ~]# ll /opt/mysqlbackup/full/
-rw-r--r--. 1 root root 659986 Jan 29 16:17 full_20210129_16171611908241.tar.gz