duanmh 发表于 2021-9-23 11:00

mysql在终端删除了某个表数据后找回的方法

一般情况下, 项目会有备份机制的,如果有没备份怎么办?
这时候看看MySQL开启回滚没。 如果没开启怎么办?
这时候可以看看是否打开了 Bin log功能,如果是开启了的,则可以从binlog恢复。如果没开怎么办?
这时候看你是删除表内的内容还是整个表, 如果是整个表,那个表存储数据的文件已近被删除,可以考虑用软件回复试试。 如果只是清除了表内的内容怎么办?
这时候看你的项目制作情况, 如果是框架制作的, 系统会记录你在程序里面执行过的所有 sql语句。
例如:Thinkphp3.X框架。 在应用目录里面有个“Runtime/Logs”目录。 里面的日志里会记录你所有应用端执行的sql语句及相关日志。
如:

这时候你就得自己写程序, 提取出里面所有的insert、update、delete 语句了。
提取出来后, 先执行完所有的insert, 然后再去执行你的其他语句, 这里需要注意的一点是要按时间的先后顺序。 另外有一点需要注意:批量添加的数据时间是一致的, 而且在多个终端执行的insert 语句时间可能前后不一, 所以提取出来后更具时间排序后再依次执行, 但是刚才说的批量执行的数据这时候插入数据库少数部分插入顺序可能会不一样, 这里需要自己核对重新调整一下。
下面以提取insert为例:
function bianli3()
    {
      $hostdir= iconv("utf-8","gbk","./Public/pmslog") ;//我存储日志的文件夹
      $filesnames = scandir($hostdir);
      $filearr = array();
      
      $errcode = array();
      //得到所有文件
      foreach ($filesnames as $name) {
            if($name!=".." && $name!=".")
            {
                //$hostdir=./Public/pmslog    $name=Admin
                $cipath = $hostdir.'/'.$name;
                //./Public/pmslog/Admin
                $cjfilenames = scandir($cipath);
                //dump($cjfilenames);   目录下的文件
                foreach($cjfilenames as $cjname)
                {
                  if($cjname!=".." && $cjname!="." &&!is_dir($cipath."/".$cjname))
                  {
                        $filearr[] = $cipath."/".$cjname;   //存储所有文件
                        
                  }
                }
            }
            
      }
      //挨个儿遍历文件。
      $insertsql = array();
      foreach ($filearr as $dqfile) {
            $f_arr = '';
            $f_arr = file($dqfile);
            foreach ($f_arr as $cont){
                if(strpos($cont,"SQL: INSERT INTO `你的表名字`") !== false){
                  $str='';    //之前因为怕了, 所以循环量我先重置了变量
                  $str = str_replace("SQL: ","",$cont);   //去头
                  $lastwz = 0;
                  $lastwz = strrpos($str,')',0);;
                  $str2 = '';
                  $str2 = substr($str,0,$lastwz+1);
                  $dianlastwx = 0;
                  $dianlastwx = strrpos($str2,',',0);

                  $addtime = 0;
                  $addtime = substr($str2,$dianlastwx-11,10);   //本语句当时的执行时间
                  if($addtime>0){
                        $insertsql[] = array('time'=>$addtime,'sql'=>$str2);
                  }else{//我的sql有两种格式, 这里是另一个种格式语句取执行时间
                        $kstime = 0;
                        $kstime = strrpos($str,'VALUES',0);
                        $lsstr3 = '';
                        $lsstr3 = substr($str2,$kstime+8,-1);
                        $lssz = array();
                        $lssz = explode(',', $lsstr3);
                        $kstime = substr($lssz,1,-1);
                        $insertsql[] = array('time'=>$kstime,'sql'=>$str2);
                  }

                }
            }
      }
      //dump($insertsql);
      $date = array_column($insertsql, 'time');
      array_multisort($date,SORT_ASC,$insertsql);   //重新排序
      array_shift($insertsql);    //第一个我不要
      $Model = M();//或者 $Model = D(); 或者 $Model = M();
      foreach ($insertsql as $dqsql) {
            $sql = $dqsql['sql'];
            $voList = $Model->execute($sql);    //执行sql
            
      }
      echo 'OK';
    }

其他sql语句同理, 只是提取的sql那里调整一下。
【以上就是我本次中秋节后误删表数据,找回经过的道路。(因为我的数据对应有操作日志,所以上述会提到:执行时间先后,目的就是为了我存储到其他表里的日志能和我找回的数据像对应)】
备份很重要!!!

shc1221 发表于 2021-9-23 11:12

感谢分享

xiajin 发表于 2021-9-23 11:42

不错,这也是一个思路,不过这个日志记录时间久了占用空间大,我这边一般都会不定时清除一下。

如果是不是RDS的话,保险一点,记得要开启Mysql bin log

笨蛋先森 发表于 2021-9-23 16:59

了解了,感谢

alterempty 发表于 2021-9-23 17:30

没有bin log就什么都不是了

lcg2014 发表于 2021-9-24 11:39

膜拜同时精通数据库和开发的大神

liubeyond 发表于 2022-1-15 11:26

能私信一份 PHP语言之年会抽奖系统 吗?谢谢 2928883@qq.com
页: [1]
查看完整版本: mysql在终端删除了某个表数据后找回的方法