MySQL目前采取的备份策略都是xtrabackup全备+binlog备份,如果当某天某张表意外的删除,那么如何快速从xtrabackup全备中恢复单表呢?从MySQL 5.6版本开始,支持可传输表空间(Transportable Tablespace),那么利用这个功能就可以实现单表的恢复,同样利用这个功能还可以把innodb表移动到另外一台服务器上。
下面进行从xtrabackup全备恢复单表的测试。
环境介绍
-
数据库版本:MySQL-5.7.22
前期准备:
1.
数据库要求:
-
innodb_file_per_table=1
-
当导入表空间时,目的库的页大小要和源库的页大小相匹配。
-
DISCARD TABLESPACE 不支持分区表。如果你在分区表上使用命令 ALTER TABLE ... DISCARD TABLESPACE 你会看到如下错误: ERROR 1031 (HY000): 表引擎没有这个选项。
-
DISCARD TABLESPACE 命令不支持有父子关系的表。如果 FOREIGN_KEY_CHECKS 被设置成1. 在使用命令之前我们可以将这一参数设置为0. FOREIGN_KEY_CHECKS=0.
-
ALTER TABLE ... IMPORT TABLESPACE 命令在导入表时不会检查主外键关系。
2.安装工具mysql-utilities:
# yum install mysql-utilities -y
或者:
# wget -c https://downloads.mysql.com/archives/get/file/mysql-utilities-1.6.5.tar.gz
# tar -xvf mysql-utilities-1.6.5.tar.gz
# cd mysql-utilities-1.5.3
# python ./setup.py build
# python ./setup.py install
查看原表中的数据:
root@localhost : test:55: > select count(*) from sbtest2;
+----------+
| count(*) |
+----------+
| 8503320 |
+----------+
1 row in set (32.21 sec)
2.1 执行备份:
# innobackupex --defaults-file=/etc/my.cnf --user=root --password=123456 /data/backup
apply-log:
# innobackupex --defaults-file=/etc/my.cnf --apply-log /data/backup
删除sbtest1表
mysql> drop table sbtest.sbtest1;
利用mysql-utilities工具读取表结构(不支持MariaDB哦)
2.2 mysqlfrm相关参数介绍:
--basedir :如 --basedir=/usr/local/percona-5.6.21
--server : 如 --server=user:password@192.168.1.100:3306
--diagnostic : 开启按字节模式来恢复frm结构
--user :启动MySQL用户,通常为mysql
[root@yuelei1 test]# mysqlfrm --diagnostic sbtest2.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 sbtest2.frm:
# The .frm file is a TABLE.
# CREATE TABLE Statement:
CREATE TABLE `sbtest2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`k` int(11) NOT NULL,
`c` char(360) NOT NULL,
`pad` char(180) NOT NULL,
PRIMARY KEY `PRIMARY` (`id`)
) ENGINE=InnoDB;
#...done.
[root@yuelei1 test]# mysqlfrm --basedir=/opt/mysql sbtest2.frm --user=root --port=3307
# Spawning server with --user=root.
# Starting the spawned server on port 3307 ... done.
# Reading .frm files
#
# Reading the sbtest2.frm file.
#
# CREATE statement for sbtest2.frm:
#
CREATE TABLE `sbtest2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`k` int(11) NOT NULL DEFAULT '0',
`c` char(120) COLLATE utf8_bin NOT NULL DEFAULT '',
`pad` char(60) COLLATE utf8_bin NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
#...done.
[root@yuelei1 test]# mysqlfrm --server=powdba:abc123@127.0.0.1:3306 sbtest2.frm --user=root --port=3307
WARNING: Using a password on the command line interface can be insecure.
# Source on 127.0.0.1: ... connected.
# Spawning server with --user=root.
# Starting the spawned server on port 3307 ... done.
# Reading .frm files
#
# Reading the sbtest2.frm file.
#
# CREATE statement for sbtest2.frm:
#
CREATE TABLE `sbtest2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`k` int(11) NOT NULL DEFAULT '0',
`c` char(120) COLLATE utf8_bin NOT NULL DEFAULT '',
`pad` char(60) COLLATE utf8_bin NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
#...done.
注:
使用--
diagnostic比
--basedir和--server模式的3倍;这应该是mysqlfrm在使用--
diagnostic
模式时,无法进行字符编码校验所致引起的。
建议:
能用--server模式时,尽量使用--server同时保证提供mysqld环境与原生产环境的一致。
2.3 执行恢复
加一个写锁,确保安全
mysql> lock tables sbtest2 write;
丢弃表空间
mysql> alter table sbtest2 discard tablespace;
Query OK, 0 rows affected (0.00 sec)
从备份中拷贝ibd文件,并且修改权限
# cp /data/backup/test/sbtest2.ibd /data/mysql/data/dba_test
# chown -R mysql.mysql /data/mysql/data
这里有警告,可以忽略。详情可以看:
https://yq.aliyun.com/articles/59271
检验查询数据是否一致:
mysql> alter table sbtest2 import tablespace;
Query OK, 0 rows affected, 1 warning (0.08 sec)
root@localhost : dba_test:51: > select count(*) from sbtest2;
+----------+
| count(*) |
+----------+
| 8503320 |
+----------+
1 row in set (54.43 sec)
最后解锁:
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)
总结:
1、
通过xtrabackup全备中的ibd文件以及frm文件恢复数据成功,这样也就代表着xtrabackup就算备份失败,只要有部分ibd文件以及frm文件保证完好,MySQL也是可以进行数据恢复的,在极端情况下也能尽可能的减少损失。但是由于xtrabackup是通过记录redo日志的方式来保存备份过程中产生的增量数据,这一部分增量数据目前还没有办法恢复。
2、
在MySQL大表迁移方案提供了一种思路:直接拷贝ibd文件的方式