记一次MySQL删库的数据恢复
2016-11-25 21:43
246 查看
昨天因为不可描述的原因,数据库直接被
drop database删除。在第一时间停止数据库服务和Web服务,备份MySQL数据目录下的所有文件之后,开始走上数据恢复之路。
第一次干这种事,各种不得法。因为我们既没有备份,也没有开启binlog,连innodb_file_per_tabe_也没有。一番折腾后向万能的朋友圈求救,朋友给了两个链接,最终救了一下命。以下先按编号记下 URL,后续引用之。
http://dba.stackexchange.com/questions/23251/is-there-a-way-to-recover-a-dropped-mysql-database
https://github.com/chhabhaiya/undrop-for-innodb
https://twindb.com/how-to-recover-innodb-dictionary/
其中URL1和URL3的内容基本上相同,是整个恢复工作的蓝本。URL2是URL1中引用的一个twindb团队开发的一个工具,现在他们官方已经删除了,URL2是该工具的一个fork,或者说是备份。
恢复过程以URL3为蓝本,先去URL2 git clone一份代码下来,然后按其说明编译,我们在ubuntu server 14.04 64bit 版本的情况下,成功编译完成,编译中需要安装各种依赖不表。
然后用
stream_parser处理
ibdata1文件,接下来恢复
SYS_TABLES和
SYS_INDEXES,建议此过程中严格遵守参考资料,比如把这些资料恢复到
dumps/default目录中,而不是随意起名,以免横生枝节。
这里还有一个坑,就是URL3里用的
c_parser -4f是会出错的,而URL1里用的是
c_parser -4Df,就不会出错,所以大家做的时候一定要把这个D加上。感叹一下,如果不细心的人真的没法做这事!摔!
接下来按URL3的说明把数据字典导入 MySQL。这一步可以不做,按URL1里高票答案的方法来获取索引ID,比较麻烦。URL3的方法应该会出这样的错:
ERROR 1148 (42000) at line 2: The used command is not allowed with this MySQL version
这是因为MySQL默认不启用
LOAD DATA LOCAL INFILE导致的,需要给
mysql命令加上
--local-infile参数。这是参考文献的一个坑。趟过这个坑以后,我可以告诉你一个捷径,就是URL2里的代码里其实有一个文件
recover_dictionary.sh,它干的就是恢复数据字典的事情,所以你只要把这个shell脚本里的
mysql都替换成
mysql --local-infile -uroot -pxxxxx就行,其中xxxx是指你的root账号密码,不过前提是你很听话的用了前面说的
dumps/default目录,不然就再多一轮替换。
接下来的内容,大部分是参考文献里没有的了。
恢复数据字典后,就可以用URL3介绍的方式找出你对应的所有数据库和表的索引ID了。这个时候就遇到为
c_parser提供数据表建表语句的问题了,这个问题难就难在先有鸡还是先有蛋,一般来说,数据库都被删掉了,哪还有办法去搞出
CREATE TABLE这种建表语句呢?好就好在我们用的是
django,它对数据迁移的完美支持救了我一命。在这里讲一句题外话,使用类似django/ror/laravel等有数据迁移框架在此就看出多么重要了。只要在根据原有项目做一次migrate,数据表就建好了,这时候只要用
mysqldump导出对应表的建表语句即可:
mysqldump --add-drop-table=0 --add-lock=0 -d DBNAME TABLENAME -uroot -p > xxxx.sql
因为
c_parser非常弱,只处理
CREATE TABLE语句,多一点干扰都不行,所以上面的参数都是必要的。
接下来就是参考URL1把某一个表的数据恢复出来,这里有一个坑,URL1里说把数据恢复到dump.tsv里,其实是不对的,这里应该用
dumps/default/TABLENAME,别问我为什么知道,我不会告诉你我找这个原因找瞎了眼,好吧,跟你说,因为生成的
load_cmd.sql里直接引用
dumps/default/TABLENAME,无法设置。所以最后我们这里可用的命令是:
./c_parser -6f pages-ibdata1/FIL_PAGE_INDEX/0000000000002410.page -t xxxx.sql > dumps/default/TABLENAME 2> load_cmd.sql
把数据恢复出来以后,执行
mysql --local-infile -uroot -p DBNAME < load_cmd.sql
就可以把数据导进去了,记得在数据库里查询一下有没有成功,如果没有数据恢复出来,应该是其中的某些环节出了问题。
这样就成功恢复了某一个表,只要按这里最后三条命令(导出建表语句、恢复数据、导入数据)重复地做下去,你就能把基本上所有的数据都恢复出来了。之所以说是“基本上”,原因是我系统中使用了
utf8mb4编码(为了兼容emoji),结果是如果数据中有emoji的内容就会在导入数据的环节出错,暂时没有找到办法恢复这个数据。
以上就是整个恢复过程,枯燥、压力山大,这种事情我不想再经历了。如果你也遇到这样的数据恢复需求,希望这篇笔记能够帮到你。但也不要指望我能帮到你更多了,我的经验也仅止于此,天大地大,就此别过,不要找我。谢谢!
相关文章推荐
- 记一次MySQL删库的数据恢复
- 记一次揪心的MySQL数据恢复过程
- 记一次mysql数据恢复
- 记一次揪心的MySQL数据恢复过程
- 记一次MySQL删库的数据恢复
- 一次血的教训,阿里云rds mysql 数据库,本地化并日志恢复已删除的两天数据
- 一次血的教训,阿里云rds mysql 数据库,本地化并日志恢复已删除的两天数据
- 记一次 mysql 数据恢复
- 记一次MySQL删库的数据恢复
- mysql:数据备份和恢复方法
- MySQL备份和恢复数据表的方法
- 一次Exchange 2003 数据恢复的历程
- MySQL数据故障时备份与恢复
- mysql和mssql的备份和恢复数据的方法
- 一次数据恢复心得
- 希捷12代一次特别的数据恢复
- 给mysql数据表加索引的一次经验与体会.
- mysql版本不一致,导致恢复数据出错
- 使用myisamchk命令进行崩溃恢复Mysql数据表
- 一次惨痛的数据恢复