这两天遇到一个奇葩问题,由于数据库报错,无法启动,为了解决问题,删除了mysql数据目录中的ib_logfile0和ib_logfile1两个文件(但我现在仍不确定是不是删除这两个文件引起的数据丢失,因为我无法重现这个问题),之后,数据库确实能够正常启动了,却发现里面有一部分(除了一个自己的库之外和mysql默认的几个库,如mysql、information_schema等)数据库虽然show tables时能够看到表,但是如果想对表进行任何操作,都提示表不存在。想要dump数据库,也没办法,毫无疑问,我的数据库找不回来了,不幸的是,这事发生在生产环境中,我必须要将数据库恢复回来!接下来就来说说怎么恢复。
首先,你要确认你的mysql是开启了日志文件的(一般来说mysql默认开启),并且没有定时清理的功能,也就是说从mysql安装到当前时间所有的mysql操作日志都在,最起码要保证你要恢复的数据库从创建到出问题的时刻的日志文件要全部都在,否则就不一定能够恢复的了了。mysql日志文件一般在mysql的data目录下,如果你在这个目录下能够看到一个或多个mysql-bin.0000xx的二进制文件并且时间是对的,那就证明mysql日志是正常工作的。至于如何开启mysql日志文件功能,请自行百度或Google。
第二步,找到你的mysql对应的data目录,每个服务器不一样,看你的my.cnf配置文件中的datadir对应的路径,确认datadir目录下的mysql-bin文件是有效完整的。
第三步,使用mysqlbinlog命令解析mysql-bin二进制文件,从中解析出你所需要的sql语句记录来,并将其写入一个sql文件中,这里要介绍一下mysqlbinlog这个命令,使用这个命令再配合参数,就可以恢复任意时段或时间点的任意数据库。
用法:mysqlbinlog [options]
常用参数:
-d,选择数据库,后跟数据库名称,如-d test,意思就是从日志文件中提取出所有test数据库的操作;
–start-datetime,开始时间,后跟时间字符串,如–start-datetime=”2015-12-25 11:25:56″,意思就是从日志文件中提取这一时间节点以后的数据库操作;
–stop-datetime,结束时间,后跟时间字符串,如–stop-datetime=”2016-12-25 11:25:56″,意思就是从日志文件中提取这一时间节点之前的数据库操作;
–start-position,开始位置,后跟一个整数,如–start-position=100,意思就是从日志文件中第1个位置等于N参量时的事件开始读取数据库操作;
–stop-position,结束位置,后跟一个整数,如–stop-position=1000,意思就是从日志文件中第1个位置等于和大于N参量时的事件起停止读取数据库操作;
最常用的参数大概就是以上五个了,如果还想了解更多参数,可以参看这个链接:http://blog.csdn.net/jbboy/article/details/42489419
因为我是要恢复某几个库的所有数据,所以我没有使用时间限制和位置限制,只是用了数据库参数,我的命令内容如下:
mysqlbinlog -d database_name –base64-output=DECODE-ROWS mysql-bin.000001 mysql-bin.000002 mysql-bin.000003 mysql-bin.000004 mysql-bin.000005 mysql-bin.000006 mysql-bin.000007 mysql-bin.000008 mysql-bin.000009 mysql-bin.000010 mysql-bin.000011 mysql-bin.000012 mysql-bin.000013 mysql-bin.000014 mysql-bin.000015 mysql-bin.000016 mysql-bin.000017 mysql-bin.000018 mysql-bin.000019 mysql-bin.000020 mysql-bin.000021 mysql-bin.000022 mysql-bin.000023 mysql-bin.000024 mysql-bin.000025 mysql-bin.000026 mysql-bin.000027 mysql-bin.000028 mysql-bin.000029 > database_name.sql
为了安全起见,我将真实的数据库名称用database_name代替。可以看到,我在一条命令里面使用了多个mysql-bin日志文件,正如我前面所说,我要恢复的是某个库的全部数据,所以我需要从这个数据库建库那一刻起,一直到当前时刻的所有操作,为了安全起见,我应用了mysql的所有日志文件,以免漏掉某一些操作,这里需要强调的一点是,这些文件是有顺序的,并非随意乱写的,需要按照这些文件的创建时间/最后修改时间顺序填写,否则可能会引起数据错乱,你可以使用ls -ltr命令将文件按照时间顺序正向排列,从而获取文件顺序。最后将日志分析产生的sql语句输出到database_name.sql文件中,你可以打开这个文件看,你会发现里面有你之前对数据库所有的插入、更新和删除操作,还有建库、建表等操作,至此,通过mysql-bin日志文件恢复数据库的操作最重要的部分已经结束了。
最后,就是将这个sql文件导入的mysql中即可,导入之前,最好先将datadir整体备份一遍,然后再将对应的数据库先drop,然后再导入该sql文件。
总结一下,因为mysql-bin中记录了当前mysql服务器所有对数据库进行修改的操作,所以通过分析mysql-bin文件可以获得对应的sql语句,然后将对应的sql语句顺序执行一遍,即可以恢复数据,也就相当于模拟从某一个时刻开始到另一时刻的所有对数据库更改的sql语句都再做一遍,对数据库的增删改全部重新做一遍,最后达到数据一致。通过这件事情,再次告诫各位维护服务器的童鞋,删东西之前要备份!!!
本文适用于你不知道表结构,也不清楚表里面的数据,你只知道表名和数据名的情况,如果你清楚表结构的话,在同样的情况下,还有另外一种恢复方式,详见下方链接,需要说明的是,这篇文章的内容我并未验证过,只是给各位提供一个参考,如果真有人如我一般不幸中招,可以尝试一下如下方法,尝试完了希望能够在本文回复一下如下方法是否有用。
链接:http://m.baidu.com/from=1307j/bd_page_type=1/ssid=0/uid=0/pu=usm%401%2Csz%40320_1001%2Cta%40iphone_2_5.1_3_537/baiduid=BD3B1337A58F64B4FF4C32EBE777D7CC/w=0_10_/t=iphone/l=3/tc?ref=www_iphone&lid=9613747448649833563&order=1&fm=alop&tj=www_normal_1_0_10_title&vit=osres&m=8&srd=1&cltj=cloud_title&asres=1&title=…ibdata1%E5%92%8Cib_logfile%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E6%81%A2%E5%A4%8DMySQL%E6%95%B0…_%E5%8D%9A%E5%AE%A2%E5%9B%AD&dict=30&w_qd=IlPT2AEptyoA_yisFVCwJ7E6vQ0WRaDzZpF5dqiUzq&sec=19031&di=a6067d4b9c041e95&bdenc=1&tch=124.395.212.677.1.518&nsrc=IlPT2AEptyoA_yixCFOxXnANedT62v3IEQGG_ytK1DK6mlrte4viZQRAWyX7M7uNEYCb9n00sqcIx8yf0WEe6so4g43&eqid=856ae45e651760001000000358ab7591&wd=&clk_info=%7B%22srcid%22%3A%221599%22%2C%22tplname%22%3A%22www_normal%22%2C%22t%22%3A1487631792866%2C%22xpath%22%3A%22div-a-h3%22%7D