4

如何仅从 TableName#P#pname.ibd 形式的 .ibd 文件中恢复分区的 mysql InnoDB 表?Chris Calendar 在此处的文章 http://www.chriscalender.com/?p=28 适用于具有单个 .ibd 文件的非分区表,但“丢弃”和“导入”步骤导致“存储引擎不分区表有此选项”错误。

Wes Smith 在上面链接的其中一条评论中建议使用手动过程一次导入一个分区,但这对我不起作用。如果我尝试按照他的方法创建一个非分区表,移动第一个重命名为 TableName.ibd 的 .ibd 文件,然后进行导入,导入成功,但表中的行数为零。随后建议的“添加回分区”步骤"alter table TableName partition by range ... (partition pname1 values less than (...) ENGINE=InnoDB)"令人震惊地用一个很小的新 TableName#P#pname1.ibd 替换了 TableName.ibd 文件(对应于第一个分区)。尝试这样做时,我丢失了一个分区的数据。我有大约 150 个分区要恢复。

关于如何从 .ibd 文件中恢复数据的任何建议?谢谢。

4

1 回答 1

1

因此,事实证明,原始帖子链接的评论中建议的方法确实有效。我在上面的“更改表...”步骤中提到的分区的删除是合法的,因为在丢失 ibdata 和日志文件之前,它已在原始表中被故意删除(但 mysql 无论如何都不会删除 .ibd 文件) . 恢复过程非常缓慢,但我设法编写了脚本并希望让它在接下来的几天内运行完成。

如果您发现自己处于类似情况,需要恢复许多分区,这里有一些提示。假设您有一个包含 100 个分区的表 TableName。通常,如果通过“create table”语句创建 100 个分区,它们将具有连续的 innodb ID,但通常情况可能并非如此,因为分区可能是在创建后添加的。所以,这里是步骤:

1)使用上面博客中Calendar的方法找出每个partition对应的innodb ID如下。注意这一步不需要重启mysql服务器。只需创建一个像 TableName 这样没有任何分区的表并丢弃它的表空间。然后将第一个分区的 .ibd 文件(命名为 TableName#P#pname1.ibd)作为 TableName.ibd 移动到数据库目录并尝试导入它。查看 mysql error.log(通常是 /var/log/mysql/error.log)以查看该分区的 innodb ID 是什么。对每个分区(或根据需要)重复此步骤,直到文件中的所有分区都有 2 元组(innodb_ID_i,partition_boundary_i)。

2)从一个空的innodb状态开始(停止服务器,删除ibdata和ib_logfile*,重新启动服务器)。对于上面步骤 1 中文件中的每个 innodb_ID 条目,创建一个表 TableName_i,如 TableName。例如,如果这 100 个分区对应的 ID 为 321、322、...、370、415、416、...464(两个块,每个块有 50 个连续 ID),那么编写一个脚本来创建 320 个虚拟表,50 个表像 TableName、45 个虚拟表和 50 个像 TableName 的表。

3) 对于上面创建的每个 TableName_i 表,

--do 

     (i) rename table TableName_i to TableName

     (ii) alter table TableName discard tablespace // important to do this step before the next one

     (iii) mv TableName#P#pname_i.ibd TableName.ibd // with the appropriate directory prefixes

     (iv) alter table TableName import tablespace

     (v) alter table partition by range (partition_field) (partition pname_i values less than (partition_boundary_i))   // This is the most and only time consuming step

     (vi) rename table TableName to TableName_i // or some other name or just dump it to a file

--repeat  

请注意,上述所有步骤都是可编写脚本的,并且不需要在任何时候重新启动服务器,除非在第 2 步开始时以空的 innodb 状态开始。在进行下一步之前,请注意在步骤 3 中引入对每个子步骤是否成功的检查,否则后续步骤可能会失败和/或 .ibd 文件可能会被覆盖。如果可行,请在步骤 3(iii) 中使用副本而不是 mv。

最后一点:使用 percona 的恢复工具包使用十六进制编辑可能会稍微简单一些,但这不适用于我的分区表情况。我遇到了同样的,看似未解决的问题,分区表如http://www.mysqlperformanceblog.com/2011/05/13/connecting-orphaned-ibd-files/的评论之一所述。不过,您的里程可能会有所不同。如果有一种方法可以避免重新创建分区(如上面的步骤 3(v)),那将是非常好的和快速的,但我不确定是否有一个。

于 2012-09-03T05:27:11.193 回答