PHP数据库分卷导出备份的实现思路

来源:互联网 发布:麦克雷 数据 编辑:程序博客网 时间:2024/05/20 06:51

在写这个功能的时候借鉴了诸多系统,例如dedeCMS,phpCMS等系统,可惜如出一辙,都有bug,他们没办法很好的控制住分卷的大小,所以自己冥思苦想,最总有了一下思路:

//如果要轉載本文請注明出處,免的出現版權紛爭,我不喜歡看到那種轉載了我的作品卻不注明出處的人 Seven{See7di#Gmail.com}
$work=StrToLower(_r($_GET["work"]));
Switch ($work){
Case "export":
_Export();
Break;
Case "exportloop":
_ExportLoop();
Break;
Case "tozip":
_Tozip();
Break;
}
/*---------------------------------*/
Function _Export(){
Global $Mysql,$work;
$f1=_r($_GET["f1"]);

//如果是第一个回圈
IF($f1=="1"){
   //首先获取一次是否指定了备份表
   $tables=$_REQUEST["tables"];
   Echo ($tables);
   IF(Empty($tables)){
    //得到数据表
    $Result=$Mysql->View("Show Tables From ".BLK_SysDbname."");
    Foreach($Result as $val){
     $tables[]=$val[0];
    }
   }Else{
    $tables=Explode(",", $tables);
    $tables=Array_Filter($tables,'_nul');
   }
   $_SESSION['Tab'] = $tables;

   //初始化数据表表序号
   $nList=0;
   //初始化文件序号
   $nFile=1;
   //用来做比较,看看是否已经写入建表信息
   $_SESSION['nList'] = ($nList-1);
}Else{
   $nList=_r($_GET["nList"]);
   $nFile=_r($_GET["nFile"]);
}
$iSql = '';        //抓取的内容
$fPath = "Cache/";      //保存目录
$cName = "DB_Export.sql";    //缓存文件
$_Tab = $_SESSION['Tab'][$nList]; //当前所操作的表
$fName = "DB".Date('_md_').$nFile.".sql";

//判断目录状况
IF(!Is_writable($fPath)){Exit("数据无法备份到服务器!请检查 ".$fPath." 目录是否可写。");}

//判断是否备份完毕
IF(Count($_SESSION['Tab'])<=$nList){
   @Unlink($fPath.$cName);
   For($i=1;$i<=$nFile;$i++){
    $FileArr[]=$fPath."DB".Date('_md_').$i.".sql";
   }
   $_FileName="DB".Date('_md').".zip";
   Tozip($FileArr,$_FileName,2,2);

   Alert("","?work=backdb&rback=1");
   Die();
}

//每次读一个表,得到头信息和建表信息
IF($_SESSION['nList'] < $nList){
   IF($nFile==1 And $nList==0){
    //删除文件
    For($i=1;$i<1000;$i++){
     IF(File_exists($fPath."DB".Date('_md_').$i.".sql")){
      @Unlink($fPath."DB".Date('_md_').$i.".sql");
     }Else{
      Break;
     }
    }
    //建立文件
    File_put_contents($fPath.$fName,"");
    File_put_contents($fPath.$cName, "");
    $iSql = "# Create by ".BLK_SysName."\n# Create time ".Date('Y-m-d')."\n# Mysql Version ".$Mysql->Version()."\n# PHP Version ".@phpversion()."\n# --------------------------------------------------------\n\nSET SQL_MODE=\"NO_AUTO_VALUE_ON_ZERO\";\n";
   }
   $iSql .= "DROP TABLE IF EXISTS `".$_Tab."`;\n";
   $_iSql = Mysql_fetch_row(mysql_query("SHOW CREATE TABLE ".$_Tab.""));
   $iSql .= $_iSql[1].";\n\n";
}

//写入头信息
$iSql=Trim(File_get_contents($fPath.$fName)."\n\n".$iSql);
File_put_contents($fPath.$fName,$iSql);

//得到缓存的内容并判断是否为空,如果为空,抓取当前表所有的内容放入缓存
$_Cache=Trim(File_get_contents($fPath.$cName));
IF(Empty($_Cache)){
   $_Cache=DropInfo($_Tab);
   File_put_contents($fPath.$cName,$_Cache);
}

//循环抓取,直到备份文件满额为止(因为循环不能及时得到文件尺寸)
Alert("","?work=exportloop&nList=".$nList."&nFile=".$nFile."&Session=".$Session."","",10);
}
/*---------------------------------*/
Function _ExportLoop(){
Global $work;
$nList=_r($_GET["nList"]);
$nFile=_r($_GET["nFile"]);
$iSql = '';        //抓取的内容
$fPath = "Cache/";      //保存目录
$fSize = (BLK_SysDbsplit*1024);   //文件大小,2048K=2M
$fName = "DB".Date('_md_').$nFile.".sql";
$cName = "DB_Export.sql";

//显示进度
Echo "<br><br><strong>备份正在进行中请稍候,现在正在生成 <span style='color:red;'>".$fName."</span></strong><br><br>";
Echo "<br>".(FileSize($fPath.$fName))."<br>".$fSize."<br><br>";
Echo Loading((FileSize($fPath.$fName)),$fSize);

//如果备份文件满了
IF(((FileSize($fPath.$fName))+9000)>$fSize){
   $nFile++;       //备份文件序号加一
   $_SESSION['nList'] = $nList; //防止再次写入建表信息
   Alert("","?work=export&nList=".$nList."&nFile=".$nFile."&Session=".$Session."","",30);
}Else{
   //取得现在缓存的内容,编译为数组
   $_Cache = (File($fPath.$cName));

   //为备份文件抓取需要的数据,每次4条
   $_Info=Array();
   For($i=0;$i<2;$i++){
    $_Info[]=$_Cache[$i];
   }

   //得到新的缓存数据
   $_Cache=array_diff_key($_Cache,$_Info);
   File_put_contents($fPath.$cName,Trim(Implode("",$_Cache)));

   //重新整理备份文件的内容并写入
   $iSql=Trim(File_get_contents($fPath.$fName))."\n".Trim(Implode("",$_Info));
   File_put_contents($fPath.$fName,$iSql);

   //如果备份文件未满而缓存空了,则进入下一个表
   IF(Count($_Cache)<1){
    $nList++;
    $_SESSION['nList'] = ($nList-1);
    Alert("","?work=export&nList=".$nList."&nFile=".$nFile."&Session=".$Session."","",10);
   //如果备份文件未满而缓存未空,则循环该函数
   }Else{
    Alert("","?work=exportloop&nList=".$nList."&nFile=".$nFile."&Session=".$Session."","",10);
   }
}
}


0 0
原创粉丝点击