• 惊心动魄的数据恢复之旅


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

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

    接下来,才是重头戏,恢复这半天的数据,从早上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);

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

  • 相关阅读:
    javascript之this的深入学习
    记一次前端面试
    nodejs学习
    Javascript内置对象
    Javascript事件
    全屏滚动插件小结
    Javascript函数的深入学习
    近年来前端开发趋势,MVVM框架,Vue.js的核心思想
    Javascript的for ... in循环
    JavaScript的对象深入学习
  • 原文地址:https://www.cnblogs.com/ddcoder/p/5793576.html
Copyright © 2020-2023  润新知