码迷,mamicode.com
首页 > 其他好文 > 详细

惊心动魄的数据恢复之旅

时间:2016-08-21 22:28:50      阅读:125      评论:0      收藏:0      [点我收藏+]

标签:

站点被攻击了,数据表丢了两张,而且是很重要的明细表,真是魂淡啊!没办法了,必须先恢复数据,平息老板+客户的怒气。

万幸的是,数据库有做差异备份,备份了一天之前的数据。先把这部分数据提取,恢复了,心率和血压顿时下降了一半。最多最多就丢了半天的数据,应该不会卖身也赔不起了。

接下来,才是重头戏,恢复这半天的数据,从早上4点到下午16点,这12个小时的数只能从bin-log上想办法。首先,找到这一天的日志文件(因为这一天日志文件涉及好几个,这边简化过程,只以一个文件来说,暂且命名为bin-log-0821)。

第一步:先们bin-log-0821转为可视明文:

mysqlbinlog --set-charset=utf8 --database=db_name --start-datetime="2016-8-21 4:00:00" --stop-datetime="2016-8-21 16:00:00" bin-log-0821 > log.sql

第二步:得到了log.sql,我们要把log.sql中,我们需要的两张表(暂且命名table1和table2)相关的sql语句提取出来。可是就在这一步,本菜遇到了一个麻烦事。就是INSERT和UPDATE语句,有可能跨行,无法很便提取出来。如果用grep -i table1 log.sql > log_result.sql,一碰到跨行的记录只有UPDATE `table1` SET 没下文了。。。

加上本菜的Shell功能又不强,所以在这个环节卡了好久。最好,通过网上一顿狂搜,搜到了以下办法:

sed -n ‘/^INSERT /,/;/p‘ log.sql > log_insert.sql

sed -n ‘/^UPDATE /,/;/p‘ log.sql > log_update.sql

最后得到的结果格式是:

UPDATE `table1` SET 

//此处省略字段设置

WHERE ...

/*!*/;

第三步:看到上面的格式,曙光终于在眼前了。本菜用PHP写了段代码,把需要的SQL都过滤了出来:

$fp=fopen(‘log_insert.sql‘,‘rb+‘);
if(!$fp) exit(‘file err‘);

while(!feof($fp))
{
    $sql=‘‘;
    $str=fgets($fp,1024);
    if(strstr($str,‘table1‘) || strstr($str,‘table2‘))
    {
        $sql.=$str;
        while(!feof($fp))
        {
            $str=fgets($fp,1024);
            if(strstr($str,‘/*‘))
            {
                break;
            }
            $sql.=$str;
        }
        $db->query($sql);
    }
    
}

fclose($fp);

 

    至此,万事大吉矣。终于恢复了需要的数据,一个周日血压升高后又回降,真心好刺激啊。

 

惊心动魄的数据恢复之旅

标签:

原文地址:http://www.cnblogs.com/ddcoder/p/5793576.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!