文档信息

原文:http://www.mysqlperformanceblog.com/2012/01/25/how-to-recover-a-single-innodb-table-from-a-full-backup/

作者Miguel Angel Nieto

日期:January 25, 2012

翻译信息

译者leopkuweibotwitter

链接:http://www.himysql.com/post/how-to-recover-a-single-innodb-table-from-a-full-backup/

翻译版本:1

翻译版权创作共享协议Attribution-ShareAlike 2.0、GNU自由文档许可证

翻译日期:2012年1月31日

译者序:曾经因为想要从完全备份文件中恢复某个InnoDB表而在搜索引擎中到处翻。这篇文章给了我们一个非常好的指导。另外,本文还涉及了为什么InnoDB不能拷贝数据库文件等话题。

有时,数据丢失的问题出现在某些表中,我们只需要从完全备份中恢复这少部分表。在这个特殊的场景中,恢复单张表要比做一次完全恢复要快得多。在MyISAM环境中,恢复单张表要容易得多,但是如果你的环境为InnoDB,这项任务就显得不那么容易了。

在Oracle原版MySQL中,我们不能任意地在数据库或服务器之间移动ibd文件。究其根源,表定义存储在InnoDB共享表空间(ibdata),而事务ID和日志序列号保存在表空间文件中,这些对于每个服务器来说都是不一样的。因此,我们的例子非常简单:先删除将要恢复表中部分行。

下述的限制在 Percona Server 中均已解除。 访问本文的结论一节获取更多信息。本文重点讨论原版 MySQL 如何恢复单张表 。

一、首先,要完成单个ibd表空间,必须满足下述先决条件:

  • ibd 文件必须是为 all insert buffer entries merged[^1],且不含有任何未提交事务一致性备份,为独立于共享ibdata表空间。也就是说,关闭服务时使用 innodb_fast_shutdown =0 选项。我们使用了XtraBackup 可以避免关闭服务

  • 备份开始后,不允许 drop、truncate 或者 alter 表结构(schema)。

  • 选项 innodb_file_per_table 必须打开。

二、导出所有数据到某个目录

export 是一个神奇的选项,将有助于我们获得一个具有完全独立 ibd 文件、不需要关闭服务的一致备份。下一步在 –export 选项上运行以 innodb_fast_shutdown=0 进行备份的恢复过程,因此,合并所有的插入缓冲区。

# innobackupex –defaults-file=/etc/my.cnf –export /tmp/

三、接着应用日志得到一个一致的备份:

# innobackupex --defaults-file=/etc/my.cnf --apply-log --export /tmp/2012-01-22_14-13-20/

四、现在,将要删除部分数据。这个例子中,我们删除 user 10008 的 salary 信息:

mysql> SELECT * FROM salaries WHERE emp_no=10008;
+--------+--------+------------+------------+
| emp_no | salary | from_date | to_date |
+--------+--------+------------+------------+
| 10008 | 46671 | 1998-03-11 | 1999-03-11 |
| 10008 | 48584 | 1999-03-11 | 2000-03-10 |
| 10008 | 52668 | 2000-03-10 | 2000-07-31 |
+--------+--------+------------+------------+

mysql> DELETE FROM salaries WHERE emp_no=10008;

五、下面的步骤将节省不少时间与脑细胞:-p我们只恢复 salaries 表而不是所有 InnoDB 数据。

  • Discard salaries表的表空间:
mysql> ALTER TABLE salaries DISCARD TABLESPACE;
  • 从备份目录拷贝 salaries.ibd 文件到数据目录:
# cp /tmp/2012-01-22_14-13-20/employees/salaries.ibd /var/lib/mysql/data/employees/
  • 导入新的表空间:
mysql> ALTER TABLE salaries IMPORT TABLESPACE;

mysql> SELECT * FROM salaries WHERE emp_no=10008;
+--------+--------+------------+------------+
| emp_no | salary | from_date | to_date |
+--------+--------+------------+------------+
| 10008 | 46671 | 1998-03-11 | 1999-03-11 |
| 10008 | 48584 | 1999-03-11 | 2000-03-10 |
| 10008 | 52668 | 2000-03-10 | 2000-07-31 |
+--------+--------+------------+------------+

user 的 salary 记录又回来了!

结论:如刚才所演示的,某个 InnoDB 表空间可以像 MyISAM 一样进行单独恢复操作。需要留意的是,这需要一些先决条件。

Percona Server 解除了很多限制,比如:alter 或 truncate 表的同时,在另外一个服务器实例中导入该表。虽然这仅适用于使用 Xtrabackup 导出的表,导出的数据中含有本来没有存在 .ibd 文件中的主要表空间的基本信息。

要想刚才所述的功能工作的话, innodb_import_table_from_xtrabackup=1 选项必须打开。访问 Percona Server扩展导出文档 获取更详细的信息。

下一篇博客,我将会阐述如何使用 Percona Data Recovery 工具集实现恢复操作。