# mysql -uroot -pR00t_123
mysql>create database test;
-
-
-
- 创建测试表
-
-
mysql>use test ;
mysql>create table tmp_list_001(id int primary key,name varchar(20));
-
-
-
- 插入测试数据
-
-
mysql>insert into tmp_list_001 values(1,'wufan');
mysql>insert into tmp_list_001 values(2,'zhangsan');
mysql>flush logs ;
-
-
-
- 全量备份
-
-
#/mybackup/xtrabackup/myfull_backup.sh
-
-
-
- 插入增量数据
-
-
mysql>insert into tmp_list_001 values(3,'lisi');
mysql>insert into tmp_list_001 values(4,'wangwu');
mysql>insert into tmp_list_001 values(5,'liutao');
mysql>flush logs ;
-
-
-
- 增量备份1
-
-
#/mybackup/xtrabackup/myincr_backup.sh
-
-
-
- 插入增量数据
-
-
mysql>insert into tmp_list_001 values(6,'liuyifei');
mysql>insert into tmp_list_001 values(7,'luozhixiang');
mysql>flush logs ;
-
-
-
- 增量备份2
-
-
#/mybackup/xtrabackup/myincr_backup.sh
-
-
-
- 插入增量数据
-
-
mysql>insert into tmp_list_001 values(8,'liudehua');
mysql>insert into tmp_list_001 values(9,'guofucheng');
mysql>flush logs ;
-
-
-
- 增量备份3
-
-
#/mybackup/xtrabackup/myincr_backup.sh
-
-
-
- 插入增量数据(binlog恢复)
-
-
mysql>insert into tmp_list_001 values(10,'zhangyuqi');
mysql>insert into tmp_list_001 values(11,'lixiaolong');
mysql>flush logs ;
-
-
-
- 检查表数据
-
-
mysql> select * from tmp_list_001 ;
+----+-------------+
| id | name |
+----+-------------+
| 1 | wufan |
| 2 | zhangsan |
| 3 | lisi |
| 4 | wangwu |
| 5 | liutao |
| 6 | liuyifei |
| 7 | luozhixiang |
| 8 | liudehua |
| 9 | guofucheng |
| 10 | zhangyuqi |
| 11 | lixiaolong |
+----+-------------+
-
-
-
- 模拟删除表
-
-
mysql> drop table tmp_list_001 ;
-
-
-
- 做binlog日志切换
-
-
mysql> show master status ;
+-----------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-----------------+----------+--------------+------------------+-------------------+
| mybinlog.000047 | 344 | | | |
+-----------------+----------+--------------+------------------+-------------------+
mysql> flush logs ;
在故障已经产生后,上来先切换下日志以便分隔开故障的日志到一个已确定的binlog日志中是个好习惯。
需要恢复的binlog日志肯定要在这个binlog日志的这个344pos位置之前。我们根据这个日志来定位具体要恢复的联机binlog日志的结束位置。
-
-
-
- 复制备份数据到测试实例
- 复制全备文件
- 复制备份数据到测试实例
-
-
#scp /mybackup/xtrabackup/full/200505165917.286 testip:/mybackup/xtrabackup/full/
-
-
-
-
- 复制增备文件
-
-
-
#scp /mybackup/xtrabackup/incr/* testip:/mybackup/xtrabackup/incr/
-
-
-
-
- 复制联机binlog文件
-
-
-
找到最后一个增备,根据xtrabackup_binlog_info文件确定联机binlog恢复开启的pos位置。
[/mybackup/xtrabackup/incr/200505170052.986]# cat xtrabackup_binlog_info
mybinlog.000046 154
结束的binlog就是2.3.5.14节中的binlog日志,将这两个binlog日志拷贝到测试实例上去。
#scp /var/mysql/log_bin/mybinlog.000046 testip:/var/mysql/log_bin/
#scp /var/mysql/log_bin/mybinlog.000047 testip:/var/mysql/log_bin/
-
-
-
- [测试实例]检查开启innodb_file_per_table参数
-
-
mysql> show variables like '%innodb_file_per_table%' ;
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_file_per_table | ON |
+-----------------------+-------+
该参数在mysql社区版5.7.29中是默认开启的。
-
-
-
- [测试实例]安装mysql-utilities
-
-
工具下载:
https://centos.pkgs.org/7/mysql-tools-x86_64/mysql-utilities-1.6.5-1.el7.noarch.rpm.html
需要的两个包都可以在该网站找到。
安装:
# rpm -ivh mysql-utilities-1.6.5-1.el7.noarch.rpm mysql-connector-python-2.1.8-1.el7.x86_64.rpm
-
-
-
- [测试实例]应用全备日志
-
-
# innobackupex \
--defaults-file=/mybackup/xtrabackup/full/200505165917.286/backup-my.cnf \
--apply-log \
--redo-only \
--user=root \
--password='R00t_123' \
--export \
/mybackup/xtrabackup/full/200505165917.286/
-
-
-
- [测试实例]应用第一次增备
-
-
# innobackupex \
--defaults-file=/mybackup/xtrabackup/full/200505165917.286/backup-my.cnf \
--apply-log \
--user=root \
--password='R00t_123' \
--export \
--redo-only \
/mybackup/xtrabackup/full/200505165917.286/ \
--incremental-dir=/mybackup/xtrabackup/incr/200505165954.893/
-
-
-
- [测试实例]应用第二次增备
-
-
# innobackupex \
--defaults-file=/mybackup/xtrabackup/full/200505165917.286/backup-my.cnf \
--apply-log \
--user=root \
--password='R00t_123' \
--export \
--redo-only \
/mybackup/xtrabackup/full/200505165917.286/ \
--incremental-dir=/mybackup/xtrabackup/incr/200505170025.134/
-
-
-
- [测试实例]应用第三次增备
-
-
innobackupex \
--defaults-file=/mybackup/xtrabackup/full/200505165917.286/backup-my.cnf \
--apply-log \
--user=root \
--password='R00t_123' \
--export \
/mybackup/xtrabackup/full/200505165917.286/ \
--incremental-dir=/mybackup/xtrabackup/incr/200505170052.986/
-
-
-
- [测试实例]读取表结构
-
-
# mysqlfrm --diagnostic /mybackup/xtrabackup/full/200505165917.286/test/tmp_list_001.frm
# WARNING: Cannot generate character set or collation names without the --server option.
# CAUTION: The diagnostic mode is a best-effort parse of the .frm file. As such, it may not identify all of the components of the table correctly. This is especially true for damaged files. It will also not read the default values for the columns and the resulting statement may not be syntactically correct.
# Reading .frm file for /mybackup/xtrabackup/full/200505165917.286/test/tmp_list_001.frm:
# The .frm file is a TABLE.
# CREATE TABLE Statement:
CREATE TABLE `test`.`tmp_list_001` (
`id` int(11) NOT NULL,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY `PRIMARY` (`id`)
) ENGINE=InnoDB;
#...done.
-
-
-
- [测试实例]建库建表
-
-
mysql> create database test ;
mysql> CREATE TABLE `test`.`tmp_list_001` (
-> `id` int(11) NOT NULL,
-> `name` varchar(20) DEFAULT NULL,
-> PRIMARY KEY `PRIMARY` (`id`)
-> ) ENGINE=InnoDB;
-
-
-
- [测试实例]对表加锁
-
-
测试环境可以不用锁表,因为数据不会变动。如果是直接在生产环境上做这个操作,最好锁表。
mysql> lock tables tmp_list_001 write ;
-
-
-
- [测试实例]丢弃表空间
-
-
[/var/lib/mysql/test]# ll
total 112
-rw-r----- 1 mysql mysql 65 May 5 16:58 db.opt
-rw-r----- 1 mysql mysql 8586 May 5 18:02 tmp_list_001.frm
-rw-r----- 1 mysql mysql 98304 May 5 18:02 tmp_list_001.ibd
mysql> alter table tmp_list_001 discard tablespace;
root@test3-dbep-db01[/var/lib/mysql/test]# ll
total 16
-rw-r----- 1 mysql mysql 65 May 5 16:58 db.opt
-rw-r----- 1 mysql mysql 8586 May 5 18:02 tmp_list_001.frm
其实discard就是将表的数据文件.ibd删除掉了,但是表的定义文件.frm还是存在的,此时表不可以做dml和查询,但是可以做ddl比如rename等操作。
-
-
-
- [测试实例]拷贝ibd文件
-
-
从已经恢复好的全备份文件中将对应的.ibd文件拷贝到数据库的数据文件目录。
#cp /mybackup/xtrabackup/full/200505165917.286/test/tmp_list_001.ibd /var/lib/mysql/test/
-
-
-
- [测试实例]修改权限
-
-
#chown -R mysql.mysql /var/lib/mysql/test/tmp_list_001.ibd
-
-
-
- [测试实例]载入表空间
-
-
mysql> alter table tmp_list_001 import tablespace;
mysql> show warnings ;
+---------+------+---------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------------------------------------------------------------------------------------------------------------+
| Warning | 1810 | InnoDB: IO Read error: (2, No such file or directory) Error opening './test/tmp_list_001.cfg', will attempt to import without schema verification |
+---------+------+---------------------------------------------------------------------------------------------------------------------------------------------------+
该告警是说没有tmp_list_001.cfg文件,可以忽略。
-
-
-
- [测试实例]解锁表
-
-
mysql> unlock tables;
-
-
-
- [测试实例]检查数据
-
-
mysql> select * from tmp_list_001 ;
+----+-------------+
| id | name |
+----+-------------+
| 1 | wufan |
| 2 | zhangsan |
| 3 | lisi |
| 4 | wangwu |
| 5 | liutao |
| 6 | liuyifei |
| 7 | luozhixiang |
| 8 | liudehua |
| 9 | guofucheng |
+----+-------------+
可以看到此时只恢复到了最后一个增量备份时候的数据,最后一次增量备份以后还有数据插入,这部分数据在联机binlog日志里面。
-
-
-
- [测试实例]恢复联机binlog日志
-
-
在对应的binlog中找到对应的drop table语句之前的一个pos,这个就是最终我们需要恢复的结束的pos。
-
-
-
- [测试实例]规整binlog日志
-
-
#mysqlbinlog -d test --start-position 154 -D /var/mysql/log_bin/mybinlog.000046 >/tmp/binlog46.log
#mysqlbinlog -d test --stop-position 219 -D /var/mysql/log_bin/mybinlog.000047 >>/tmp/binlog46.log
这个地方是只有两个联机binlog日志需要恢复,如果有多个,在中间的binlog日志不需要设置开始或者结束pos,只有一头一尾需要指定pos,开头只需要指定开始的start-pos,结束只需要指定stop-pos。
-
-
-
- [测试实例]筛选指定表的日志记录
-
-
每个mysql产生的原始binlog文件的开头都是这样一个东西,指定了binlog的偏移量、版本这些东西,指定Format_description_event的格式,每个会话加一句就行了。没有这个后面的语句没法执行,会报下面的错:
ERROR 1609 (HY000): The BINLOG statement of type `Table_map` was not preceded by a format description BINLOG statement.
# grep -A7 -w DELIMITER /tmp/binlog46.log |grep -A5 "Start: binlog v 4" | head -6 >/tmp/tb_name.sql
下面这句是筛选出针对tmp_list_001表的相关语句的执行,不同版本,不同binlog格式的情况可能不一样,需要灵活处理。
# grep -B7 -A12 -w tmp_list_001 /tmp/binlog46.log >> /tmp/tb_name.sql
-
-
-
- [测试实例]最终文件内容
-
-
# cat /tmp/tb_name.sql
#200505 17:00:45 server id 1 end_log_pos 123 CRC32 0x0eb02f63 Start: binlog v 4, server v 5.7.29-log created 200505 17:00:45
BINLOG '
PSuxXg8BAAAAdwAAAHsAAAAAAAQANS43LjI5LWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAEzgNAAgAEgAEBAQEEgAAXwAEGggAAAAICAgCAAAACgoKKioAEjQA
AWMvsA4=
'/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=8/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 291
#200505 17:01:03 server id 1 end_log_pos 349 CRC32 0x86825264 Table_map: `test`.`tmp_list_001` mapped to number 1776
# at 349
#200505 17:01:03 server id 1 end_log_pos 399 CRC32 0xf5297af3 Write_rows: table id 1776 flags: STMT_END_F
BINLOG '
TyuxXhMBAAAAOgAAAF0BAAAAAPAGAAAAAAEABHRlc3QADHRtcF9saXN0XzAwMQACAw8CFAACZFKC
hg==
TyuxXh4BAAAAMgAAAI8BAAAAAPAGAAAAAAEAAgAC//wKAAAACXpoYW5neXVxafN6KfU=
'/*!*/;
# at 399
#200505 17:01:03 server id 1 end_log_pos 430 CRC32 0xa80d1c14 Xid = 531
COMMIT/*!*/;
# at 430
--
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 495
#200505 17:01:09 server id 1 end_log_pos 567 CRC32 0x164362ad Query thread_id=34 exec_time=0 error_code=0
SET TIMESTAMP=1588669269/*!*/;
BEGIN
/*!*/;
# at 567
#200505 17:01:09 server id 1 end_log_pos 625 CRC32 0x3624c56a Table_map: `test`.`tmp_list_001` mapped to number 1776
# at 625
#200505 17:01:09 server id 1 end_log_pos 676 CRC32 0xd2eeb7d9 Write_rows: table id 1776 flags: STMT_END_F
BINLOG '
VSuxXhMBAAAAOgAAAHECAAAAAPAGAAAAAAEABHRlc3QADHRtcF9saXN0XzAwMQACAw8CFAACasUk
Ng==
VSuxXh4BAAAAMwAAAKQCAAAAAPAGAAAAAAEAAgAC//wLAAAACmxpeGlhb2xvbmfZt+7S
'/*!*/;
# at 676
#200505 17:01:09 server id 1 end_log_pos 707 CRC32 0x65cbcdec Xid = 532
COMMIT/*!*/;
# at 707
-
-
-
- [测试实例]应用筛选的日志
-
-
mysql> source /tmp/tb_name.sql
Query OK, 0 rows affected (0.00 sec)
Charset changed
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected, 1 warning (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
-
-
-
- [测试实例]验证数据
-
-
mysql> select * from tmp_list_001 ;
+----+-------------+
| id | name |
+----+-------------+
| 1 | wufan |
| 2 | zhangsan |
| 3 | lisi |
| 4 | wangwu |
| 5 | liutao |
| 6 | liuyifei |
| 7 | luozhixiang |
| 8 | liudehua |
| 9 | guofucheng |
| 10 | zhangyuqi |
| 11 | lixiaolong |
+----+-------------+
可以看到最后在联机binlog日志里面的两条数据也已经恢复了。
-
-
-
- [生产环境]生产环境建表
-
-
mysql> CREATE TABLE `test`.`tmp_list_001` (
-> `id` int(11) NOT NULL,
-> `name` varchar(20) DEFAULT NULL,
-> PRIMARY KEY `PRIMARY` (`id`)
-> ) ENGINE=InnoDB;
该表结构同样跟测试库一样,从备份而来。见2.3.5.23小节。
-
-
-
- [生产环境]丢弃表空间
-
-
mysql> ALTER TABLE tmp_list_001 DISCARD TABLESPACE;
root@test3-dbep-db01[/var/lib/mysql/test]# ll
total 16
-rw-r----- 1 mysql mysql 65 May 5 16:58 db.opt
-rw-r----- 1 mysql mysql 8586 May 5 21:40 tmp_list_001.frm
-
-
-
- [测试环境]测试环境导出表空间
-
-
mysql> FLUSH TABLES tmp_list_001 FOR EXPORT;
# ll
total 116
-rw-r----- 1 mysql mysql 65 May 5 16:58 db.opt
-rw-r----- 1 mysql mysql 400 May 5 22:53 tmp_list_001.cfg
-rw-r----- 1 mysql mysql 8586 May 5 21:40 tmp_list_001.frm
-rw-r----- 1 mysql mysql 98304 May 5 22:39 tmp_list_001.ibd
会多生成个tmp_list_001.cfg文件,后面我们将.cfg和.ibd文件拷贝到生产环境。
-
-
-
- [测试实例]拷贝到生产环境
-
-
#scp /var/lib/mysql/test/tmp_list_001.{ibd,cfg} ipprod:/var/lib/mysql/test/
-
-
-
- [测试实例]解锁
-
-
mysql> UNLOCK TABLES;
语句FLUSH TABLES tmp_list_001 FOR EXPORT;会加锁,所以导出完成以后需要解锁。
-
-
-
- [生产环境]修改权限
-
-
# chown -R mysql:mysql /var/lib/mysql/test/tmp_list_001.{ibd,cfg}
-
-
-
- [生产环境]导入表空间
-
-
mysql> ALTER TABLE tmp_list_001 IMPORT TABLESPACE;
-
-
-
- [生产环境]检查数据
-
-
mysql> select * from tmp_list_001 ;
+----+-------------+
| id | name |
+----+-------------+
| 1 | wufan |
| 2 | zhangsan |
| 3 | lisi |
| 4 | wangwu |
| 5 | liutao |
| 6 | liuyifei |
| 7 | luozhixiang |
| 8 | liudehua |
| 9 | guofucheng |
| 10 | zhangyuqi |
| 11 | lixiaolong |
-
-
-
- 适用条件说明
-
-
1、必须开启 innodb_file_per_table。
2、当这个表处于quiesced状态(就是对该表执行了FLUSH TABLES ... FOR EXPORT语句),甚至不能被select。
3、测试实例和生产实例的page size要一致。
4、5.7 版本之前,不支持分区表transport。
5、外键相关的表,必须设置 foreign_key_checks=0 才能成功
6、ALTER TABLE ... IMPORT TABLESPACE 不需要.cfg metadata file . 但是,这样的话,MySQL就不会对schema进行verificate
7、5.6以及更高版本,import&export 版本必须在同一个series(同一个系列的mysql)。
8、在replication环境中,master & slave 都必须开启 innodb_file_per_table。这个参数在社区版5.7.29中默认就是开的。
9、对于InnoDB general tablespace,不支持discard & import tablespace。
10、如果两边服务器的table row_format设置的不一样,会导致schema mismatch error
mysql> show variables like '%row_format%' ;
+---------------------------+---------+
| Variable_name | Value |
+---------------------------+---------+
| innodb_default_row_format | dynamic |
+---------------------------+---------+
- 加密过的InnoDB tablespace 必须要拷贝.cfg 文件。
该方式的恢复花费时间的地方在于export和import,但是仍然比mysqldump和mysqlimport快很多。