明輝手游網(wǎng)中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

沒有虛擬主機的小型Mysql數(shù)據(jù)庫備份腳本

[摘要]最近工作中常常需要備份遠程服務器上的Mysql數(shù)據(jù)庫到本機,一開始采用直接備份Mysql的data目錄的辦法,但由于編碼不同的原因經(jīng)常產(chǎn)生問題。后來朋友推薦我使用一個非常方便小巧的PHP程序——MyDB。一共包含三個文件:1. mydb.php //DB類代碼如下:<? class db{ ...
最近工作中常常需要備份遠程服務器上的Mysql數(shù)據(jù)庫到本機,一開始采用直接備份Mysql的data目錄的辦法,但由于編碼不同的原因經(jīng)常產(chǎn)生問題。后來朋友推薦我使用一個非常方便小巧的PHP程序——MyDB。一共包含三個文件:

1. mydb.php //DB類

代碼如下:

<? 
class db{ 
var $linkid; 
var $sqlid; 
var $record; 
function db($host="",$username="",$password="",$database="") 
    { 
    if(!$this->linkid)  @$this->linkid = mysql_connect($host, $username, $password) or die("連接服務器失敗."); 
    @mysql_select_db($database,$this->linkid) or die("無法打開數(shù)據(jù)庫"); 
    return $this->linkid;} 
function query($sql) 
    {if($this->sqlid=mysql_query($sql,$this->linkid)) return $this->sqlid; 
    else { 
        $this->err_report($sql,mysql_error); 
    return false;} 
    } 
function nr($sql_id="") 
    {if(!$sql_id) $sql_id=$this->sqlid; 
    return mysql_num_rows($sql_id);} 
function nf($sql_id="") 
    {if(!$sql_id) $sql_id=$this->sqlid; 
    return mysql_num_fields($sql_id);} 
function nextrecord($sql_id="") 
    {if(!$sql_id) $sql_id=$this->sqlid; 
    if($this->record=mysql_fetch_array($sql_id))  return $this->record; 
    else return false; 
    } 
function f($name) 
    { 
    if($this->record[$name]) return $this->record[$name]; 
    else return false; 
    } 
function close() {mysql_close($this->linkid);} 
function lock($tblname,$op="WRITE") 
    {if(mysql_query("lock tables ".$tblname." ".$op)) return true; else return false;} 
function unlock() 
    {if(mysql_query("unlock tables")) return true; else return false;} 
function ar() { 
    return @mysql_affected_rows($this->linkid); 
  } 
function i_id() { 
        return mysql_insert_id(); 
    } 
function err_report($sql,$err) 
    { 
echo "Mysql查詢錯誤<br>"; 
echo "查詢語句:".$sql."<br>"; 
echo "錯誤信息:".$err; 
    } 
/****************************************類結(jié)束***************************/ 
}?>


2. backup.php //備份腳本

代碼如下:

<? 
global $mysqlhost, $mysqluser, $mysqlpwd, $mysqldb; 
$mysqlhost="localhost"; //host name 
$mysqluser="root";              //login name 
$mysqlpwd="";              //password 
$mysqldb="";        //name of database 
include("mydb.php"); 
$d=new db($mysqlhost,$mysqluser,$mysqlpwd,$mysqldb); 
/*--------------界面--------------*/if(!$_POST['act']){/*----------------------*/ 
$msgs[]="服務器備份目錄為backup"; 
$msgs[]="對于較大的數(shù)據(jù)表,強烈建議使用分卷備份"; 
$msgs[]="只有選擇備份到服務器,才能使用分卷備份功能"; 
show_msg($msgs); 
?> 
<form name="form1" method="post" action="backup.php"> 
  <table width="99%" border="1" cellpadding='0' cellspacing='1'> 
    <tr align="center" class='header'><td colspan="2">數(shù)據(jù)備份</td></tr> 
    <tr><td colspan="2">備份方式</td></tr> 
    <tr><td><input type="radio" name="bfzl" value="quanbubiao">        備份全部數(shù)據(jù)</td><td>備份全部數(shù)據(jù)表中的數(shù)據(jù)到一個備份文件</td></tr> 
    <tr><td><input type="radio" name="bfzl" value="danbiao">備份單張表數(shù)據(jù)  
        <select name="tablename"><option value="">請選擇</option> 
          <? 
        $d->query("show table status from $mysqldb"); 
        while($d->nextrecord()){ 
        echo "<option value='".$d->f('Name')."'>".$d->f('Name')."</option>";} 
        ?> 
        </select></td><td>備份選中數(shù)據(jù)表中的數(shù)據(jù)到單獨的備份文件</td></tr> 
    <tr><td colspan="2">使用分卷備份</td></tr> 
    <tr><td colspan="2"><input type="checkbox" name="fenjuan" value="yes"> 
        分卷備份 <input name="filesize" type="text" size="10">K</td></tr> 
    <tr><td colspan="2">選擇目標位置</td></tr> 
    <tr><td colspan="2"><input type="radio" name="weizhi" value="server" checked>備份到服務器</td></tr><tr class="cells"><td colspan='2'> <input type="radio" name="weizhi" value="localpc"> 
        備份到本地</td></tr> 
    <tr><td colspan="2" align='center'><input type="submit" name="act" value="備份"></td></tr> 
  </table></form> 
<?/*-------------界面結(jié)束-------------*/}/*---------------------------------*/ 
/*----*/else{/*--------------主程序-----------------------------------------*/ 
if($_POST['weizhi']=="localpc"&&$_POST['fenjuan']=='yes') 
    {$msgs[]="只有選擇備份到服務器,才能使用分卷備份功能"; 
show_msg($msgs); pageend();} 
if($_POST['fenjuan']=="yes"&&!$_POST['filesize']) 
    {$msgs[]="您選擇了分卷備份功能,但未填寫分卷文件大小"; 
show_msg($msgs); pageend();} 
if($_POST['weizhi']=="server"&&!writeable("./backup")) 
    {$msgs[]="備份文件存放目錄'./backup'不可寫,請修改目錄屬性"; 
show_msg($msgs); pageend();} 
/*----------備份全部表-------------*/if($_POST['bfzl']=="quanbubiao"){/*----*/ 
/*----不分卷*/if(!$_POST['fenjuan']){/*--------------------------------*/ 
if(!$tables=$d->query("show table status from $mysqldb")) 
    {$msgs[]="讀數(shù)據(jù)庫結(jié)構(gòu)錯誤"; show_msg($msgs); pageend();} 
$sql=""; 
while($d->nextrecord($tables)) 
    { 
    $table=$d->f("Name"); 
    $sql.=make_header($table); 
    $d->query("select * from $table"); 
    $num_fields=$d->nf(); 
    while($d->nextrecord()) 
    {$sql.=make_record($table,$num_fields);} 
    } 
$filename=date("Ymd",time())."_all.sql"; 
if($_POST['weizhi']=="localpc") down_file($sql,$filename); 
elseif($_POST['weizhi']=="server") 
    {if(write_file($sql,$filename)) 
$msgs[]="全部數(shù)據(jù)表數(shù)據(jù)備份完成,生成備份文件'./backup/$filename'"; 
    else $msgs[]="備份全部數(shù)據(jù)表失敗"; 
    show_msg($msgs); 
    pageend(); 
    } 
/*-----------------不要卷結(jié)束*/}/*-----------------------*/ 
/*-----------------分卷*/else{/*-------------------------*/ 
if(!$_POST['filesize']) 
    {$msgs[]="請?zhí)顚憘浞菸募志泶笮?quot;; show_msg($msgs);pageend();} 
if(!$tables=$d->query("show table status from $mysqldb")) 
    {$msgs[]="讀數(shù)據(jù)庫結(jié)構(gòu)錯誤"; show_msg($msgs); pageend();} 
$sql=""; $p=1; 
$filename=date("Ymd",time())."_all"; 
while($d->nextrecord($tables)) 
{ 
    $table=$d->f("Name"); 
    $sql.=make_header($table); 
    $d->query("select * from $table"); 
    $num_fields=$d->nf(); 
    while($d->nextrecord()) 
    {$sql.=make_record($table,$num_fields); 
    if(strlen($sql)>=$_POST['filesize']*1000){ 
            $filename.=("_v".$p.".sql"); 
            if(write_file($sql,$filename)) 
            $msgs[]="全部數(shù)據(jù)表-卷-".$p."-數(shù)據(jù)備份完成,生成備份文件'./backup/$filename'"; 
            else $msgs[]="備份表-".$_POST['tablename']."-失敗"; 
            $p++; 
            $filename=date("Ymd",time())."_all"; 
            $sql="";} 
    } 
} 
if($sql!=""){$filename.=("_v".$p.".sql");         
if(write_file($sql,$filename)) 
$msgs[]="全部數(shù)據(jù)表-卷-".$p."-數(shù)據(jù)備份完成,生成備份文件'./backup/$filename'";} 
show_msg($msgs); 
/*---------------------分卷結(jié)束*/}/*--------------------------------------*/ 
/*--------備份全部表結(jié)束*/}/*---------------------------------------------*/ 
/*--------備份單表------*/elseif($_POST['bfzl']=="danbiao"){/*------------*/ 
if(!$_POST['tablename']) 
    {$msgs[]="請選擇要備份的數(shù)據(jù)表"; show_msg($msgs); pageend();} 
/*--------不分卷*/if(!$_POST['fenjuan']){/*-------------------------------*/ 
$sql=make_header($_POST['tablename']); 
$d->query("select * from ".$_POST['tablename']); 
$num_fields=$d->nf(); 
while($d->nextrecord()) 
    {$sql.=make_record($_POST['tablename'],$num_fields);} 
$filename=date("Ymd",time())."_".$_POST['tablename'].".sql"; 
if($_POST['weizhi']=="localpc") down_file($sql,$filename); 
elseif($_POST['weizhi']=="server") 
    {if(write_file($sql,$filename)) 
$msgs[]="表-".$_POST['tablename']."-數(shù)據(jù)備份完成,生成備份文件'./backup/$filename'"; 
    else $msgs[]="備份表-".$_POST['tablename']."-失敗"; 
    show_msg($msgs); 
    pageend(); 
    } 
/*----------------不要卷結(jié)束*/}/*------------------------------------*/ 
/*----------------分卷*/else{/*--------------------------------------*/ 
if(!$_POST['filesize']) 
    {$msgs[]="請?zhí)顚憘浞菸募志泶笮?quot;; show_msg($msgs);pageend();} 
$sql=make_header($_POST['tablename']); $p=1;  
    $filename=date("Ymd",time())."_".$_POST['tablename']; 
    $d->query("select * from ".$_POST['tablename']); 
    $num_fields=$d->nf(); 
    while ($d->nextrecord())  
    {     
        $sql.=make_record($_POST['tablename'],$num_fields); 
       if(strlen($sql)>=$_POST['filesize']*1000){ 
            $filename.=("_v".$p.".sql"); 
            if(write_file($sql,$filename)) 
            $msgs[]="表-".$_POST['tablename']."-卷-".$p."-數(shù)據(jù)備份完成,生成備份文件'./backup/$filename'"; 
            else $msgs[]="備份表-".$_POST['tablename']."-失敗"; 
            $p++; 
            $filename=date("Ymd",time())."_".$_POST['tablename']; 
            $sql="";} 
    } 
if($sql!=""){$filename.=("_v".$p.".sql");         
if(write_file($sql,$filename)) 
$msgs[]="表-".$_POST['tablename']."-卷-".$p."-數(shù)據(jù)備份完成,生成備份文件'./backup/$filename'";} 
show_msg($msgs); 
/*----------分卷結(jié)束*/}/*--------------------------------------------------*/ 
/*----------備份單表結(jié)束*/}/*----------------------------------------------*/ 
/*---*/}/*-------------主程序結(jié)束------------------------------------------*/ 
function write_file($sql,$filename) 
{ 
$re=true; 
if(!@$fp=fopen("./backup/".$filename,"w+")) {$re=false; echo "failed to open target file";} 
if(!@fwrite($fp,$sql)) {$re=false; echo "failed to write file";} 
if(!@fclose($fp)) {$re=false; echo "failed to close target file";} 
return $re; 
} 
function down_file($sql,$filename) 
{ 
    ob_end_clean(); 
    header("Content-Encoding: none"); 
    header("Content-Type: ".(strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') ? 'application/octetstream' : 'application/octet-stream')); 
    header("Content-Disposition: ".(strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') ? 'inline; ' : 'attachment; ')."filename=".$filename); 
    header("Content-Length: ".strlen($sql)); 
    header("Pragma: no-cache"); 
    header("Expires: 0"); 
    echo $sql; 
    $e=ob_get_contents(); 
    ob_end_clean(); 
} 
function writeable($dir) 
{ 
    if(!is_dir($dir)) { 
    @mkdir($dir, 0777); 
    } 
    if(is_dir($dir))  
    { 
    if($fp = @fopen("$dir/test.test", 'w')) 
        { 
@fclose($fp); 
    @unlink("$dir/test.test"); 
    $writeable = 1; 
}  
    else { 
$writeable = 0; 
    } 
} 
    return $writeable; 
} 
function make_header($table) 
{global $d; 
$sql="DROP TABLE IF EXISTS ".$table."\n"; 
$d->query("show create table ".$table); 
$d->nextrecord(); 
$tmp=preg_replace("/\n/","",$d->f("Create Table")); 
$sql.=$tmp."\n"; 
return $sql; 
} 
function make_record($table,$num_fields) 
{global $d; 
$comma=""; 
$sql .= "INSERT INTO ".$table." VALUES("; 
for($i = 0; $i < $num_fields; $i++)  
{$sql .= ($comma."'".mysql_escape_string($d->record[$i])."'"); $comma = ",";} 
$sql .= ")\n"; 
return $sql; 
} 
function show_msg($msgs) 
{ 
$title="提示:"; 
echo "<table width='100%' border='1'  cellpadding='0' cellspacing='1'>"; 
echo "<tr><td>".$title."</td></tr>"; 
echo "<tr><td><br><ul>"; 
while (list($k,$v)=each($msgs)) 
    { 
    echo "<li>".$v."</li>"; 
    } 
echo "</ul></td></tr></table>"; 
} 
function pageend() 
{ 
exit(); 
} 
?>


3. restore.php //還原腳本

代碼如下:

<? 
session_start(); 
global $mysqlhost, $mysqluser, $mysqlpwd, $mysqldb; 
$mysqlhost="localhost"; //host name 
$mysqluser="root";              //login name 
$mysqlpwd="";              //password 
$mysqldb="";        //name of database 
include("mydb.php"); 
$d=new db($mysqlhost,$mysqluser,$mysqlpwd,$mysqldb); 
/******界面*/if(!$_POST['act']&&!$_SESSION['data_file']){/**********************/ 
$msgs[]="本功能在恢復備份數(shù)據(jù)的同時,將全部覆蓋原有數(shù)據(jù),請確定是否需要恢復,以免造成數(shù)據(jù)損失"; 
$msgs[]="數(shù)據(jù)恢復功能只能恢復由dShop導出的數(shù)據(jù)文件,其他軟件導出格式可能無法識別"; 
$msgs[]="從本地恢復數(shù)據(jù)需要服務器支持文件上傳并保證數(shù)據(jù)尺寸小于允許上傳的上限,否則只能使用從服務器恢復"; 
$msgs[]="如果您使用了分卷備份,只需手工導入文件卷1,其他數(shù)據(jù)文件會由系統(tǒng)自動導入"; 
show_msg($msgs); 
?> 
<form action="" method="post" enctype="multipart/form-data" name="restore.php"> 
<table width="91%" border="0" cellpadding="0" cellspacing="1"> 
<tr align="center" class="header"><td colspan="2" align="center">數(shù)據(jù)恢復</td></tr> 
<tr><td width="33%"><input type="radio" name="restorefrom" value="server" checked> 
從服務器文件恢復 </td><td width="67%"><select name="serverfile"> 
    <option value="">-請選擇-</option> 
<? 
$handle=opendir('./backup'); 
while ($file = readdir($handle)) { 
    if(eregi("^[0-9]{8,8}([0-9a-z_]+)(\.sql)$",$file)) echo "<option value='$file'>$file</option>";} 
closedir($handle);  
?> 
  </select> </td></tr> 
<tr><td><input type="radio" name="restorefrom" value="localpc">       從本地文件恢復</td> 
<td><input type="hidden" name="MAX_FILE_SIZE" value="1500000"><input type="file" name="myfile"></td></tr> 
<tr><td colspan="2" align="center"> <input type="submit" name="act" value="恢復"></td>  </tr></table></form> 
<?/**************************界面結(jié)束*/}/*************************************/ 
/****************************主程序*/if($_POST['act']=="恢復"){/**************/ 
/***************服務器恢復*/if($_POST['restorefrom']=="server"){/**************/ 
if(!$_POST['serverfile']) 
    {$msgs[]="您選擇從服務器文件恢復備份,但沒有指定備份文件"; 
     show_msg($msgs); pageend();    } 
if(!eregi("_v[0-9]+",$_POST['serverfile'])) 
    {$filename="./backup/".$_POST['serverfile']; 
    if(import($filename)) $msgs[]="備份文件".$_POST['serverfile']."成功導入數(shù)據(jù)庫"; 
    else $msgs[]="備份文件".$_POST['serverfile']."導入失敗"; 
    show_msg($msgs); pageend();         
    } 
else 
    { 
    $filename="./backup/".$_POST['serverfile']; 
    if(import($filename)) $msgs[]="備份文件".$_POST['serverfile']."成功導入數(shù)據(jù)庫"; 
    else {$msgs[]="備份文件".$_POST['serverfile']."導入失敗";show_msg($msgs);pageend();} 
    $voltmp=explode("_v",$_POST['serverfile']); 
    $volname=$voltmp[0]; 
    $volnum=explode(".sq",$voltmp[1]); 
    $volnum=intval($volnum[0])+1; 
    $tmpfile=$volname."_v".$volnum.".sql"; 
    if(file_exists("./backup/".$tmpfile)) 
        { 
        $msgs[]="程序?qū)⒃?秒鐘后自動開始導入此分卷備份的下一部份:文件".$tmpfile.",請勿手動中止程序的運行,以免數(shù)據(jù)庫結(jié)構(gòu)受損"; 
        $_SESSION['data_file']=$tmpfile; 
        show_msg($msgs); 
        sleep(3); 
        echo "<script language='javascript'>";  
        echo "location='restore.php';";  
        echo "</script>";  
        } 
    else 
        { 
        $msgs[]="此分卷備份全部導入成功"; 
        show_msg($msgs); 
        } 
    } 
/**************服務器恢復結(jié)束*/}/********************************************/ 
/*****************本地恢復*/if($_POST['restorefrom']=="localpc"){/**************/ 
    switch ($_FILES['myfile']['error']) 
    { 
    case 1: 
    case 2: 
    $msgs[]="您上傳的文件大于服務器限定值,上傳未成功"; 
    break; 
    case 3: 
    $msgs[]="未能從本地完整上傳備份文件"; 
    break; 
    case 4: 
    $msgs[]="從本地上傳備份文件失敗"; 
    break; 
    case 0: 
    break; 
    } 
    if($msgs){show_msg($msgs);pageend();} 
$fname=date("Ymd",time())."_".sjs(5).".sql"; 
if (is_uploaded_file($_FILES['myfile']['tmp_name'])) { 
    copy($_FILES['myfile']['tmp_name'], "./backup/".$fname);} 
if (file_exists("./backup/".$fname))  
    { 
    $msgs[]="本地備份文件上傳成功"; 
    if(import("./backup/".$fname)) {$msgs[]="本地備份文件成功導入數(shù)據(jù)庫"; unlink("./backup/".$fname);} 
    else $msgs[]="本地備份文件導入數(shù)據(jù)庫失敗"; 
    } 
else ($msgs[]="從本地上傳備份文件失敗"); 
show_msg($msgs); 
/****本地恢復結(jié)束*****/}/****************************************************/ 
/****************************主程序結(jié)束*/}/**********************************/ 
/*************************剩余分卷備份恢復**********************************/ 
if(!$_POST['act']&&$_SESSION['data_file']) 
{ 
    $filename="./backup/".$_SESSION['data_file']; 
    if(import($filename)) $msgs[]="備份文件".$_SESSION['data_file']."成功導入數(shù)據(jù)庫"; 
    else {$msgs[]="備份文件".$_SESSION['data_file']."導入失敗";show_msg($msgs);pageend();} 
    $voltmp=explode("_v",$_SESSION['data_file']); 
    $volname=$voltmp[0]; 
    $volnum=explode(".sq",$voltmp[1]); 
    $volnum=intval($volnum[0])+1; 
    $tmpfile=$volname."_v".$volnum.".sql"; 
    if(file_exists("./backup/".$tmpfile)) 
        { 
        $msgs[]="程序?qū)⒃?秒鐘后自動開始導入此分卷備份的下一部份:文件".$tmpfile.",請勿手動中止程序的運行,以免數(shù)據(jù)庫結(jié)構(gòu)受損"; 
        $_SESSION['data_file']=$tmpfile; 
        show_msg($msgs); 
        sleep(3); 
        echo "<script language='javascript'>";  
        echo "location='restore.php';";  
        echo "</script>";  
        } 
    else 
        { 
        $msgs[]="此分卷備份全部導入成功"; 
        unset($_SESSION['data_file']); 
        show_msg($msgs); 
        } 
} 
/**********************剩余分卷備份恢復結(jié)束*******************************/ 
function import($fname) 
{global $d; 
$sqls=file($fname); 
foreach($sqls as $sql) 
    { 
    str_replace("\r","",$sql); 
    str_replace("\n","",$sql); 
    if(!$d->query(trim($sql))) return false; 
    } 
return true; 
} 
function show_msg($msgs) 
{ 
$title="提示:"; 
echo "<table width='100%' border='1'  cellpadding='0' cellspacing='1'>"; 
echo "<tr><td>".$title."</td></tr>"; 
echo "<tr><td><br><ul>"; 
while (list($k,$v)=each($msgs)) 
    { 
    echo "<li>".$v."</li>"; 
    } 
echo "</ul></td></tr></table>"; 
} 
function pageend() 
{ 
exit(); 
} 
?>

文件結(jié)構(gòu)非常清晰,只要在文件2和3里面設置好數(shù)據(jù)庫服務器的地址、用戶名、密碼就可以備份還原數(shù)據(jù)了。需要注意的是:

·使用時候要在同級目錄下建一個Backup目錄,權(quán)限需要可寫,用于存放導出的腳本。
·當備份的數(shù)據(jù)庫比較大的時候,服務器腳本超時時間要調(diào)大一些。
·支持分卷備份,還原時候只要選擇分卷備份的第一個腳本就會自動還原所有的腳本。
·分卷文件大小不要太大,最好不超過2MB。
·安全起見,腳本不用時候記得從服務器上刪除。

【相關(guān)推薦】

1. Mysql免費視頻教程

2. 教你如何啟動和停止Mysql服務之一

3. mysql中處理特殊sql語句的實例教程

4. 刪除表的sql語句在不同數(shù)據(jù)庫中的寫法詳解

5. 教你如何用一臺機器運行多個 MySQL 服務

以上就是沒有虛擬主機的小型Mysql數(shù)據(jù)庫備份腳本的詳細內(nèi)容,更多請關(guān)注php中文網(wǎng)其它相關(guān)文章!


學習教程快速掌握從入門到精通的SQL知識。