【问题标题】:How do I recreate an FRM file for an MySQL InnoDB table with only the ibdata and *.ibd files?如何为仅包含 ibdata 和 *.ibd 文件的 MySQL InnoDB 表重新创建 FRM 文件?
【发布时间】:2017-02-01 00:42:10
【问题描述】:

这与我在 stackoverflow 上看到的相关 InnoDB 修复问题略有不同。

假设我在 MySQL 5.1 数据库中使用 innodb_file_per_table=1 恢复了以下内容:

db/tablename.ibd
innodb/ibdata1
innodb/ib_logfile0
innodb/ib_logfile1

我丢失了db/tablename.frm 文件。我可以启动数据库服务器,但 InnoDB 抱怨:

110723 13:26:33  InnoDB: Error: table 'db/tablename'
InnoDB: in InnoDB data dictionary has tablespace id 5943,
InnoDB: but tablespace with that id or name does not exist. Have
InnoDB: you deleted or moved .ibd files?

如何重建 FRM 文件?

【问题讨论】:

    标签: mysql database innodb restore database-restore


    【解决方案1】:

    编辑:我创建了一个简单的脚本来执行下面描述的所有步骤:https://ourstickys.com/recover.sh


    老问题,但我发现了这种更简单的方法:https://dba.stackexchange.com/questions/16875/restore-table-from-frm-and-ibd-file

    I have recovered my MySQL 5.5 *.ibd and *.frm files with using MySQL Utilites and MariaDB 10.
    
    1) Generating Create SQLs.
    You can get your create sql's from frm file. You must use : https://dev.mysql.com/doc/mysql-utilities/1.5/en/mysqlfrm.html
    
    shell> mysqlfrm --server=root:pass@localhost:3306 c:\MY\t1.frm --port=3310
    
    Other way you may have your create sql's.
    
    2) Create Your Tables
    Create your tables on the database.
    
    3) alter table xxx discard tablespace
    Discard your tables which do you want to replace your *.ibd files.
    
    4) Copy your *.ibd files (MySQL Or MariaDB) to MariaDB's data path
    First i try to use MySQL 5.5 and 5.6 to restrore, but database crashes and immediately stops about tablespace id broken error. (ERROR 1030 (HY000): Got error -1 from storage engine) 
    After i have used MariaDB 10.1.8, and i have succesfully recovered my data.
    
    5) alter table xxx import tablespace
    When you run this statement, MariaDB warns about file but its not important than to recover your data :) Database still continues and you can see your data.
    
    I hope this information will helpful for you.
    

    我补充一下,你可以在这里下载mysqlfrm:https://dev.mysql.com/downloads/utilities/


    我还发现了一种使用dbsake 获取CREATE TABLE 的更快方法:

    curl -s http://get.dbsake.net > dbsake
    chmod u+x dbsake
    

    然后:

    #only one table
    ./dbsake frmdump /path/to/table.frm > recover.sql
    
    #multiple tables
    ./dbsake frmdump /path/to/*.frm > recover.sql
    

    后跟:

    mysql -uUSER -p recover_db < recover.sql
    

    如果你愿意,你也可以在一行中执行它:

    ./dbsake frmdump /path/to/*.frm | mysql -uUSER -p recover_db
    

    此时您可以按照上述说明从第 3 点开始。

    【讨论】:

    • 因为我必须为 100 多个表执行此操作,所以我创建了一个脚本来为我执行此操作:ourstickys.com/recover.sh
    • 我希望我能 +100。这是一个拯救生命的解决方案。
    • 这是现在可以使用的 ;) 谢谢。但该脚本无法访问。
    【解决方案2】:

    我自己想出了一个解决方案。

    简单的解决方案是找到您保存的CREATE TABLE SQL 副本,在开发实例上运行它,然后将生成的 FRM 文件复制到恢复的实例。

    但是,就我而言,我没有可用的CREATE TABLE 命令副本。

    您可以获得运行 ibdata、ib_logfiles 和 *.ibd 文件的 MySQL 服务器。但是,如果没有 FRM,数据库中似乎就没有表。

    1. 在恢复的数据库中,运行create table innodb_table_monitor (a int) ENGINE=InnoDB
    2. 观察 MySQL 服务器错误文件,直到表监视器数据被转储(通常大约一分钟)
    3. 运行drop table innodb_table_monitor
    4. 停止恢复的数据库

    5. 编写 SQL 以匹配表监视器输出,例如:

      TABLE: name db/mylosttable, id 0 7872, flags 1, columns 5, indexes 1, appr.rows 1828
      COLUMNS: id: DATA_MYSQL DATA_NOT_NULL len 12; name: type 12 DATA_NOT_NULL len 45;     
      DB_ROW_ID: DATA_SYS prtype 256 len 6; DB_TRX_ID: DATA_SYS prtype 257 len 6; 
      DB_ROLL_PTR: DATA_SYS prtype 258 len 7;
      INDEX: name GEN_CLUST_INDEX, id 0 17508, fields 0/5, uniq 1, type 1
      root page 3, appr.key vals 1828, leaf pages 9, size pages 10
      FIELDS:  DB_ROW_ID DB_TRX_ID DB_ROLL_PTR id name
      

      可以表示为:

      drop table if exists mylosttable;
      create table mylosttable (
          id char(12) NOT NULL,
          name varchar(45) NOT NULL
      );
      

      如果您对表监视器输出感到困惑,请查看具有已知架构的表的输出。

    6. 在 MySQL 的开发实例上运行上述 SQL

    7. 将开发服务器中创建的 FRM 文件复制到恢复的数据库中。您将在相应数据库的子目录中的 MySQL 数据目录中找到它们。

    8. 重启恢复的数据库

      请注意,您可以将 FRM 文件复制到实时数据库实例中。上面停止服务器的原因是,如果您在创建 innodb_table_monitor 表后使数据库崩溃,它将使 ibdata 文件处于不一致状态,您必须从备份重新开始。

    9. 使用select * 语句测试表是否工作。如果你错了,你会看到:

      ERROR 2013 (HY000): Lost connection to MySQL server during query
      

    这意味着数据库已经崩溃了。

    如果发生这种情况,请在开发实例上执行 create table innodb_table_monitor... 并将输出与恢复实例的原始输出进行比较。你可能会看到你错过了一个 NOT NULL 或类似的小东西。

    【讨论】:

    • 多么痛苦。我希望有人提供更简单的东西。在那之前,你有我的 +1。
    猜你喜欢
    • 2012-08-18
    • 2019-01-30
    • 1970-01-01
    • 2022-07-23
    • 2021-09-03
    相关资源
    最近更新 更多