2018年5月21日,吃饱了没事干,想搞邮件服务器,百度找到个叫U-mail的东西。

进了官网,感觉挺好,脑子抽了,直接生产环境上装了,发现很垃圾,卸载。

rpm一看,包很多,写了个脚本一键删了。

删完重启,心想生产环境不会被他弄坏吧。一看wp,完蛋了,打不开了。

看了下本地服务器上的数据库备份。发现最新的备份是3月8号的。

我4,5月份写了那么多笔记啊!!!!!!!

开始想办法恢复数据。

systemstl status mysql

发现mysql这个服务都不存在了,完蛋。

cd /usr/local/mysql

看一下物理目录还在吗,能进去,还在。

数据库的数据文件一般保存在/usr/local/mysql/var/数据库名字 内,进去看了一下,文件都在。

.idb格式的是数据内容  .frm格式的是数据结构

现在要做的就是把这些东西恢复成数据库的数据。

换了台机子,重新装了mysql同版本,进了/usr/local/mysql/var 把原机子上的数据库源文件复制进去,重启数据库,数据库直接报错。

网上查了下,说是改一下/etc/my.cnf文件,添加innodb_force_recovery=1-6 就可以了。试了一遍,不行。痛苦。

后来问了下猫叔。猫叔给了个链接,并祝我好运。

https://www.cnblogs.com/xj2015/p/7479999.html

简述一下操作流程。。。

首先查看一下/etc/my.cnf中的innodb_file_per_table值是不是1

如果是1的话有可能用自动化工具修好,不是1的话只能手动修复。

看了下我的,发现是1,试一下自动工具。

mysqlibd

此工具需要Windows环境 .net4.x版本、MySQL5.6的最新版本。

mysql5.6.40  http://125.71.5.35:2333/index.php?share/file&user=1&sid=bagrDdQw

工具使用方式:

InnoDBRestore     

例如

InnoDBRestore root pass 3306 c:\dbcopy my_database

祝好运吧。如果运气好,无报错, c:\dbcopy 下的MyISAM和InnoDB数据都会被导入 my_database(my_database不需要提前创建)。

然而你可能会和我一样,遇上了数据错误(天知道为什么),导入过程可能会报错。这些报错很可能是连接被关闭

restoring : wp_posts.frm

unknown error:MySql.Data.MySqlClient.MySqlException (0x80004005): Fatal error encountered during command execution. —> MySql.Data.MySqlClient.MySqlException (0x80004005): Fatal error encountered attempting to read the resultset. —> MySql.Data.MySqlClient.MySqlException (0x80004005): Reading from the stream has failed. —> System.IO.IOException: 无法从传输连接中读取数据: 远程主机强迫关闭了一个现有的连接。。 —> System.Net.Sockets.SocketException: 远程主机强迫关闭了一个现有的连接。

然后同时,查看数据库的err日志,可能会有类似以下报错:

InnoDB: Error: trying to access page number 1372160 in space 1, InnoDB: space name recovery1/wp_posts, InnoDB: which is outside the tablespace bounds. InnoDB: Byte offset 0, len 16384, i/o type 10. InnoDB: If you get this error at mysqld startup, please check that InnoDB: your my.cnf matches the ibdata files that you have in the InnoDB: MySQL server.

由于InnoDB引擎遇上了异常,MySQL崩溃退出,导致连接断开。这种情况下,到MySQL的data目录下,删除刚才导入的数据库的文件夹以及ib_logfile0、ib_logfile1、ibdata1(也就是重置所有InnoDB引擎相关数据)。然后再启动MySQL。

将引发故障的表文件(ibd、frm)单独移出来,留作阶段2修复使用,再次执行InnoDBRestore,如再遇上故障重复以上步骤,直到工具不再报错为止。

使用mysqldump将表导出来。建议添加–skip-extended-insert参数以便数据检查,如果上面一切都顺利,无论是导入还是导出都没有任何报错,也需要仔细检查恢复出来的数据是否有异常(很大的负数、数据参杂乱码、不合理的日期等),有些情况下会有隐性损坏情况。如果没有,那么恭喜你数据就恢复完成了,不需要继续向下阅读了

……然而你可能像我一样,导出时再次遇上相似故障

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

查看err日志后,发现另一个原先看起来成功导入的ibd文件dump时由于数据错误也失败了,修改my.cnf,添加innodb_force_recovery=6。然后再重新启动,再次尝试dump查看是否成功,如成功需要仔细检查是否数据正确。如果连 innodb_force_recovery=6 也无法获得正确数据的话,只能跳过出故障的表,将其余正常的表导出。出故障的表通过第二阶段进行修复。

总的来说,我wp_posts这张表挂了,无法用自动工具修复,在数据库中想要查看这张表,数据库就会崩溃。

只能尝试手动修复这张表了。

要用到工具https://github.com/chhabhaiya/undrop-for-innodb 并且要在有mysql环境的linux上运行。

安装undrop-for-innodb工具,只需要执行make命令进行编译,很简单也非常快。

该工具可用于很多 InnoDB 灾难性数据丢失场景的数据库救援。救援的意思是尽量恢复数据,通常需要这个工具的场合都是很糟糕的,运气好的情况下你或许能全部提取出。因此无论如何依然不能直接拷贝InnoDB数据库。p.s.今年1月此工具停止进一步开发了,很可惜

make编译后会在其目录生成以下可执行工具:

c_parser innochecksum_changer stream_parser

1.使用

./stream_parser -f wp_posts.ibd

拆出ibd文件结构

2.使用mysqlfrm拆出包含表结构的CREATE TABLE语句,在第一阶段 zcgonvh的工具里有一个Windows的MySqlFrm.exe亦可使用,这里以该工具为例。Linux的 mysqlfrm可以参考下面本文后杂记

mysqlfrm 例如: mysqlfrm root pass 3306 c:\dbcopy

会在同目录下对每个frm文件生成一个.sql文件 内含创建表语句。注意该工具生成的CREATE TABLE语句不含分号,会对之后操作造成影响,需要在语句末尾添加一个分号

3.拆出的ibd文件结构会存储在pages-wp_posts.ibd里。包含以下子目录:

FIL_PAGE_INDEX:一般PAGE,依照其ID存放

FIL_PAGE_TYPE_BLOB: 如果遇上较大的数据(例如comments里有text类型的数据并且内容较多),InnoDB会使用BLOB类PAGE存储数据。需检查此目录是否有文件。如有,说明此表使用了BLOB,之后提取命令需要用-b参数指定此目录进行提取

按照步骤1拆分ibdata1,然后编辑recover_dictionary.sh脚本里的mysql命令行 在后面加上 -u root -p密码

然后执行此脚本,会将SYS系列表导入test数据库

使用mysql命令行进入test数据库后,执行:

mysql> select * from SYS_TABLES where NAME like “%/wp_posts”;

此table的ID为116,然后执行

mysql>  SELECT * FROM SYS_INDEXES where table_id=116;

即可获得主键的index_id为218,因此对应的page是:pages-wp_posts.ibd/FIL_PAGE_INDEX/0000000000000218.page。

如果没有ibddata1的情况下就没法用工具判断id了,只能一个一个猜了

使用c_parser命令对每个page尝试提取。此表数据结构是COMPACT,因而使用参数-5。如果是MYSQL5.6以上的格式用-6。不确定的话5和6都试下

本例BLOB目录下有文件,需要-b参数指定BLOB目录以确保数据完整。

步骤2得到的表结构定义(CREATE TABLE)放在 wp_posts.frm.sql

将输出指向到less以便阅读:

[root@Test undrop-for-innodb]#./c_parser -5f ./pages-wp_posts.ibd/FIL_PAGE_INDEX/XXXXX.page -b ./pages-wp_posts.ibd/FIL_PAGE_TYPE_BLOB/ -t ./wp_posts.frm.sql | less

XXXXX替换成具体的page编号,建议从头开始尝试(对两个有类似问题的表修复的结果似乎暗示第一个的成功概率最高),直到获得了明显正确的结果(日期正确 大部分数据正常 Records list为Valid)

c_parser会将tsv数据dump到标准输出管道,并且很贴心的将对应数据恢复SQL命令特意单独输出到了错误输出(某个N年未更新的工具还需要自行构建命令导入)。可以使用以下命令对含有正确数据索引的page做最终导出:

./c_parser -5f pages-wp_posts.ibd/FIL_PAGE_INDEX/0000000000224178.page -b pages-wp_posts.ibd/FIL_PAGE_TYPE_BLOB/ -t wp_posts.frm.sql > wp_posts 2> wp_posts.sql

会得到

wp_posts:提取出来的tsv格式数据 wp_posts.sql:将tsv导入数据库的SQL命令

编辑器打开这两个文件,可以看到wp_posts.sql实际上保存了原先数据表的结构

wp_posts则是保存了具体数据。

我们需要将这两个文件挪到/tmp文件夹(规避权限问题),然后修改 wp_posts.sql 内的LOAD DATA LOCAL INFILE路径,使之符合新的tsv文件路径。

之后要做的就很简单了

新建一个和原先表结构完全一样的表,然后SOURCE /tmp/wp_posts.sql;就能将数据导进数据库了。

最后dump出来,就是标准的SQL格式了。

能正常访问了!

弄完一想,如果以后渗透的时候,机子权限有了,但是没数据库权限,可以把idb文件和frm文件搞下来,然后离线脱裤!不错不错:)