如何恢复文件被移动的 InnoDB 表

atx*_*dba 15 mysql innodb disk-space

所以我有一个在复制流上设置的测试数据库服务器。在名称上出现了一个优化,它迅速填满了 slaves 数据目录上的空间。Mysql 尽职尽责地等待更多空间。

这个 datadir 是一个文件系统,只用作 mysql 的 datadir,所以没有其他东西可以释放。

我有一个 4 g innodb 测试表,它不是复制流的一部分,所以我想我会尝试一些东西来看看它是否有效,作为一个测试环境,如果事情出现严重错误,我并不太担心。

这是我采取的步骤

  1. 冲洗了我正要移动的桌子
  2. 在它上面放置了一个读锁(即使没有写入它并且它不在复制流中)
  3. 将 .frm 和 .ibd 复制到带有一些空闲空间的文件系统
  4. 解锁了桌子
  5. 截断该表 - 这为优化完成释放了足够的空间,复制开始再次开始。
  6. 停止从属/关闭 mysql
  7. 将文件从 tmp 复制回数据目录
  8. 重启mysql

.err 日志中没有显示任何内容,看起来不错。我连接并使用 mydb;并查看我在展示表中弄乱的表。但是,如果我尝试

select * from testtable limit 10;
Run Code Online (Sandbox Code Playgroud)

我收到错误

ERROR 1146 (42S02): Table 'mydb.testtable' doesn't exist
Run Code Online (Sandbox Code Playgroud)

到目前为止,我可以从所有其他表中读取数据,并且复制开始备份,没有任何抱怨。

我能做些什么来从这一点上恢复过来吗?如果需要,我可以从头开始重建它,但很好奇其他人对这次冒险的总体看法。我采取的一系列步骤是否有任何结果会导致更​​完美的结果?

如果这不是一个测试服务器,我不能只是“实时运行”看看会发生什么?如果我不得不喜欢,有什么最好的方法可以暂时释放生产从站上的空间?

Rol*_*DBA 16

大多数人忘记 TRUNCATE TABLE 的最大事情是TRUNCATE TABLE 是 DDL 而不是 DML。在 InnoDB 中,ibdata1 中的元数据包含 InnoDB 表的编号列表。使用 TRUNCATE TABLE 会导致 InnoDB 表的内部元数据 ID 发生变化。发生这种情况是因为 TRUNCATE TABLE 有效地执行以下操作:

示例:截断名为 mydb.mytb 的 InnoDB 表

USE mydb
CREATE TABLE newtb LIKE mytb;
ALTER TABLE mytb RENAME oldtb;
ALTER TABLE newtb RENAME mytb;
DROP TABLE oldtb;
Run Code Online (Sandbox Code Playgroud)

因此,新的 mytb 将具有不同的内部元数据 ID。

当您将 .ibd 文件复制到其他位置时,.ibd 中包含原始内部元数据 ID。简单地将 .ibd 文件放回去不会导致内部元数据 ID 与 ibdata1 中的元数据 ID 一致。

你应该做的是:

复制 InnoDB 表的 .ibd 文件。然后,运行这个

ALTER TABLE tablename DISCARD TABLESPACE;
Run Code Online (Sandbox Code Playgroud)

要稍后将其恢复,请将 .ibd 文件复制回 datadir,然后运行

ALTER TABLE tablename IMPORT TABLESPACE;
Run Code Online (Sandbox Code Playgroud)

这将保留内部元数据 ID。

确保 .frm 始终存在。

我曾经帮助一个客户恢复他以同样方式处理的 30 个 InnoDB 表。我不得不使用另一个数据库服务器并通过添加和删除 InnoDB 表来玩一些游戏来寻找正确的内部元数据 ID。

客户端找到了这篇文章:http : //www.chriscalender.com/?tag=innodb-error-tablespace-id-in-file。我们使用了它,它帮助很大。我希望它能帮助你。