当前位置: 首页 > 科技观察

MySQL如何使用ibd文件恢复数据?

时间:2023-03-14 19:50:08 科技观察

前言数据库丢失的痛苦。磁盘坏道、断电等意外虽然不正常,但也足以让你“惊心动魄”!如果数据丢失是因为数据库损坏导致Binlog不可用,怎么办呢~~为了在短时间内恢复数据不丢失保证业务稳定,除了使用binlog,我们还实践了一个新恢复技能!我们使用比较频繁的两种数据库恢复方式是:以上两种方式都可以实时回滚,但是你觉得这两种技巧够用吗?不...!在这个错综复杂的网络结构中,其实有很多我们无法预知的未知原因。比如下面这种情况:硬盘因劳累而失去生命,长出了坏道,导致数据库损坏。并且刚刚破坏了ibdata文件和binlog文件。那么,如果你还想着定时备份+binlog恢复的方案,那是不可能的。只能用定点备份来恢复文件吗?经过深思熟虑,作为运维人员,我们是绝对不会实施专门的Lostfiles的,因为这对业务影响太大了,但是我们还能怎么办呢?接下来,我们就放个大招!!!首先查看数据库环境,是否开启了独立表空间,如果开启了,那么恭喜,很有可能可以恢复所有数据。我们可以依靠各个数据库目录下的frm和ibd文件来实现数据恢复。一般来说,如果使用了InnoDB但没有启用独立表空间,那么所有的数据库表信息和元数据都会写入到ibdata文件中,这个文件会持续很长时间。如果在运行中,ibdata文件会越来越大,数据库的性能会下降。InnoDB提供了启用独立表空间的参数,可以让数据独立存储。这样ibdata文件只是用来存放一些引擎相关的索引信息,实际的数据写入到独立的frm和ibd文件中。好了,有了frm和ibd文件,我们就可以开始尝试数据恢复了。他的过程比binlog恢复还惊险有趣!首先我们看一下ibd和frm的说明:.frm文件:保存了各个表的数据Metadata,包括表结构的定义等,这个文件与数据库引擎无关。.ibd文件:InnoDB引擎开启独立表空间(在my.ini中配置innodb_file_per_table=1)来存放表的数据和索引文件。我们都知道,对于InnoDB数据库,如果不复制整个数据目录,而只是复制指定的数据库目录到新的实例中,数据库将无法被识别。那么如何根据这两个文件来恢复数据库呢?恢复思路:由于ibdata文件中存放了一些引擎的索引信息,ibdata文件损坏导致表名索引丢失,无法启动。那么我们可以先将原来旧的整个数据目录重命名为备份,然后重新初始化数据库生成新的ibdata文件,然后重新创建原来的数据库和对应的表,最后把备份的表空间id号改成新创建的表空间idnumber(ibdata文件中每个表都有一个唯一的表空间索引id,id随着新表的创建数递增),这样就可以恢复原数据库了。例如:库名:test_restore表结构:db_struc.sql表文件:G_RESTORE.ibd、G_RESTORE.frm1。新建库并导入表结构#mysql-uroot–p****-e“createdatabasetest_restore”#mysql-uroot–p****test_restoretest_restore.sql#mysql-uroot–p******test_restore/tmp/生成的ibd.txt文件,格式如下:(库名-表名-SpaceId)2.新建表,查看当前表空间id(假设空间id为10)#mysql-uroot–p******-e”createtabletest.tt(abool)”#hexdump-Cmysql/test/tt.ibd|head-n3|tail-n1|awk'{printstrtonum(“0x”$6$7)}'3.先创建所有库,准备所有表结构,编写脚本,根据空间id号自动新建表,准备数据库表结构,可以从备份文件中取出(我们的备份方式是结构和数据分开备份),也可以备份复制它来自具有相同表结构的其他服务器。参考备份语句:mysqldump-uroot–p******-d${db}–T/data/backup/${db}/创建原始数据库:mysql-uroot–p******-e"createdatabase${db}"restoretableidcreatetablescript:#!/bin/bash#因为前面假设是10,所以createoid=11from11#打开前面生成的ibd.txt文件,读取逐行取“库名-表名-SpaceId”cat/tmp/ibd.txt|whilereaddbtbid;do#如果我们需要恢复类别表,它的id是415,本着id创建和增加的原则automatically,即415-11=404,#我们还需要循环创建404张表,然后才真正导入分类表结构。for((oid;oid/tmp/ibd2.txt确认一致后,将备份的.ibd文件复制到新的数据库实例目录下,修改my.cnfinnodb_force_recovery=6innodb_purge_threads=0启动数据库。后续步骤和单表恢复类似,只是导出恢复到原实例即可。当然,这种方法是在数据库极端情况下不得不采用的方法。线上最重要的就是做好主从同步,定时备份,避免这样的风险。InnoDB引擎独立表空间说明:对于用过MySQL的人来说,最开始用的最多的是MyISAM表引擎。本引擎的数据库会创建三个文件:表结构、表索引、表数据空间。我们可以将一个数据库目录直接迁移到其他数据库中,这样就可以正常工作了。但是,当您使用InnoDB时,一切都会改变。默认情况下,InnoDB会将所有的数据库InnoDB引擎表数据存储在一个共享空间:ibdata1,感觉不太舒服。添加或删除数据库时,ibdata1文件不会自动收缩,单个数据库的备份也会成为问题。通常只能使用mysqldump将数据导出,再导入来解决这个问题。但是可以通过修改MySQL配置文件[mysqld]段中的innodb_file_per_table参数开启独立表空间模式,每个数据库的每个表都会生成一个数据空间。优点:1.每个表都有自己独立的表空间。2、每个表的数据和索引都会存在于自己的表空间中。3、可以实现单表在不同数据库中的移动。4.空间可回收(除droptable操作外,表空间不能自行回收)a)droptable操作自动回收表空间。对于统计分析或者日值表,删除大量数据后,可以使用:altertableTableNameengine=innodb;收回未使用的空间。b)使用innodb-plugin的Innodb使用turncatetable也会缩小空间。c)对于使用独立表空间的表,不管怎么删除,表空间的碎片都不会严重影响性能,还是有机会处理的。缺点:单表增量太大,比如100多G。结论:共享表空间在Insert操作上优势不大。没有其他独立表空间表现良好。启用独立表空间时,请合理调整:innodb_open_files。配置方法:1.innodb_file_per_table设置。开启方式:在my.cnf中的[mysqld]下设置innodb_file_per_table=12。查看是否开启:mysql>showvariableslike'%per_table%';3、关闭独占表空间innodb_file_per_table=0关闭独立表空间mysql>showvariableslike'%per_table%';