昨天因为不可描述的原因,数据库直接被 drop database删除。在第一时间停止数据库服务和Web服务,备份MySQL数据目录下的所有文件之后,开始走上数据恢复之路。

第一次干这种事,各种不得法。因为我们既没有备份,也没有开启binlog,连innodb_file_per_tabe_也没有。一番折腾后向万能的朋友圈求救,朋友给了两个链接,最终救了一下命。以下先按编号记下 URL,后续引用之。

  1. http://dba.stackexchange.com/questions/23251/is-there-a-way-to-recover-a-dropped-mysql-database
  2. https://github.com/chhabhaiya/undrop-for-innodb
  3. 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_TABLESSYS_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删库的数据恢复的更多相关文章

  1. 搭建mysql主从复制和删库数据恢复策略

    搭建主从复制 主机: [mysqld] 下增加 vim /etc/my.cnf ## 设置 server_id,一般设置为 IP server_id=8 # # 复制过滤:需要备份的数据库,输出 bi ...

  2. 怎么避免从删库到跑路 -- 详解 mysql binlog 的配置与使用

    1. 引言 使用数据库的时候,我们每个操作都十分小心,尤其是不能直接在数据库上执行 update.delete 等操作,否则万一忘记加全 where 条件,可能就会造成无法挽回的结果. 有一句十分流行 ...

  3. MySQL数据库无完整备份删库,除了跑路还能怎么办?

    1.背景 前段时间,由于运维同事的一次误操作,清空了内网核心数据库,导致了公司内部管理系统长时间不可用,大量知识库内容由于没有备份险些丢失. 结合这两天微盟的删库跑路事件,我们可以看到,数据库的备份与 ...

  4. Mysql binlog备份数据及恢复数据,学会这个,我在也不怕删库跑路啦~

    导读 我一直都主张,技多不压身(没有学不会的技术,只有不学习的人),多学一项技能,未来就少求人一次.网上经常听到xxx删库跑路,万一真的遇到了,相信通过今天的学习,也能将数据再恢复回来~~~ 当然啦, ...

  5. MySQL 多实例删库脚本

    DB版本:5.5.14 OS:CentOS 6.3 在测试环境中,在一台服务器上创建多个实例,在每个实例中一个一个删库比较麻烦,因此用下面脚本,可以直接删除所有库,除了系统库以外: #!/bin/ba ...

  6. Mysql如何在删库后可以不用跑路

    我一直在想,地球上这么多程序员,应该有很多人在团队做项目的时候,出过很大的错误,比如说不小心删了库,活动福利字段多写了个零导致全服务器玩家领到数倍奖励,听了沙雕群友的话执行rm -rf命令. 记得有一 ...

  7. 教你如何6秒钟往MySQL插入100万条数据!然后删库跑路!

    教你如何6秒钟往MySQL插入100万条数据!然后删库跑路! 由于我用的mysql 8版本,所以增加了Timezone,然后就可以了 前提是要自己建好库和表. 数据库test, 表user, 三个字段 ...

  8. MySQL从删库到跑路(一)——MySQL数据库简介

    作者:天山老妖S 链接:http://blog.51cto.com/9291927 一.MySQL简介 1.MySQL简介 MySQL是一个轻量级关系型数据库管理系统,由瑞典MySQL AB公司开发, ...

  9. 学会这个删库再也不用跑路了~ --技术流ken

    前言 相信每一个学IT的人或多或少都听说过从删库到跑路这个梗~下图也是在各种交流群屡禁不止,新人听着也是瑟瑟发抖. 人们茶余饭后,街头巷角难免要问... 下面技术流ken就教给各位新手们一招删库再也不 ...

随机推荐

  1. hive:创建索引

    hive也是支持索引的使用,但是如果表中已经有数据的情况下,创建索引的过程不是特别快. 已经拥有表: create table if not exists llcfpd_withgroupbykey( ...

  2. python中的多线程

    一个程序可以理解为一个进程,这个进程有其代号,可以依据这个代号将其杀死. 一个进程肯定有且只有一个主线程,他可以有很多子线程. 运行一个任务如果可以有许多子线程同时去做,当然会提高效率. 但是,在py ...

  3. Oracle中如何导出存储过程、函数、包和触发器的定义语句?如何导出表的结构?如何导出索引的创建语句?

    Oracle中如何导出存储过程.函数.包和触发器的定义语句?如何导出表的结构?如何导出索引的创建语句? QQ群里有人问:如何导出一个用户下的存储过程?   麦苗答:方法有多种,可以使用DBMS_MET ...

  4. C# 传统四舍五入保留两位小数(网上流传好多错误的版本)

    关于C#里面的Math.Round,很多人都会用到,而且以为是四舍五入,其实不是这样的: C#里面的Math.Round是符合IEEE标准的“四舍五入”,其实是五舍六入. 网上好多流传的下面这种方式实 ...

  5. 0418 jQuery笔记(添加事件、each、prop、$(this))

    1.添加点击事件.each.prop.$(this) //全选框的被动操作 //定义一个标志保存最终状态 var flag = false; //为每一个选择框添加点击事件,数组.click() $( ...

  6. [LeetCode] Self Dividing Numbers 自整除数字

    A self-dividing number is a number that is divisible by every digit it contains. For example, 128 is ...

  7. Python系列之 - python数据类型

    原链接:https://blog.csdn.net/m0_37745438/article/details/79572884 学习一门语言,往往都是从Hello World开始. 但是笔者认为,在一个 ...

  8. Shell编程-项目部署(一)

    由于实际工作中经常用到需要部署项目,比较麻烦,今天记录下如何利用shell脚本完成自动部署的工作,毕竟不是专业的运维出身,写的不好,还请勿喷_^o^_ 今天以部署Django项目为演示,进行部署项目, ...

  9. ●POJ 2983 Is the Information Reliable?

    题链: http://poj.org/problem?id=2983 题解: 差分约束. 1).对于条件(P u v w),不难发现反映到图上就是: $dis[u]-dis[v]=w$,所以添加两条边 ...

  10. 洛谷P2388 阶乘之乘

    题目背景 不告诉你-- 题目描述 求出1!*2!*3!*4!*--*n!的末尾有几个零 输入输出格式 输入格式: n(n<=10^8) 输出格式: 有几个零 输入输出样例 输入样例#1: 复制 ...