top
Loading...
一個MySQL數據備份/恢復的簡易方法

方法一:

query($sql);  }   //將生成的臨時備份文件合在一起  $outfile = date("Y-m-d").".sql";    if(file_exists($dbdir.$outfile)) @unlink($dbdir.$outfile);    $fpr = fopen($dbdir.$outfile, "a");  foreach($txtname as $txt){   if(file_exists($dbdir.$txt)){    //讀取臨時備份文件    $tdata = readfiles($dbdir.$txt);            //生成備份文件    $tbl = explode(".", $txt);    $str = "`".$tbl[0]."`{{".$tdata."}}";    if(fwrite($fpr, $str)){     echo $tbl[0]."...寫入 $outfile 成功!
"; }else{ echo $tbl[0]."...寫入 $outfile 失敗!
"; } @unlink($dbdir.$txt); } } fclose($fpr); }else{//恢復數據 $tdata = readfiles($dbdir.$_POST["sqlfile"]); preg_match_all("/`(.*)`{{(.*)}}/isU", $tdata, $data_ar); foreach($data_ar[1] as $k => $tt){ if(empty($data_ar[2][$k])) continue; $tfile = $dbdir.$tt.".txt"; $fp = fopen($tfile, "w"); if(fwrite($fp, $data_ar[2][$k])){ //清空表 $sql = "TRUNCATE TABLE `$tt`"; $db->query($sql); //重新裝入數據 $sql = "LOAD DATA LOW_PRIORITY INFILE '".$dbdir.$tt.".txt"."' INTO TABLE `$tt`"; if($db->query($sql)){ fclose($fp); echo $tt."表數據恢復成功!
"; unlink($dbdir.$tt.".txt"); }else{ echo $tt."表數據恢復失敗!
"; } } } //echo $tdata; //print_r($data_ar); //exit; }} /* * 讀取文件內容 * 參數 $file 為文件名及完整路徑 * 返回文件內容 */ function readfiles($file){ $tdata = ""; $fp = fopen($file, "r"); if(filesize($file) <= 0) return; while($data = fread($fp, filesize($file))){ $tdata .= $data; } fclose($fp); return $tdata; }?>

方法二:

想在PHP后臺管理直接能夠備份數據庫,于是想呀想,一直沒有什么思路,一開始是考慮用php來訪問服務器安裝mysql的目錄,比如 /usr/local/mysql/data目錄,直接把下面對應的文件進行備份,但是出現了問題:

第一、運行php的是apche的用戶,比如是nobody,那么它一般是沒有權限訪問/usr/local/mysql/data目錄的

第二、就算能夠訪問,那么你如何能夠把/usr/local/mysql/data目錄下的文件拷貝出來呢?因為mysql在運行的時候是不運行訪問的,那么nobody用戶有權限停止mysql的服務,不可能!

越想越不對勁,沒有辦法,看能不能從php操作數據庫入手,于是就去看了下phpMyadmin和Discuz!的代碼,呵呵,于是偷抄了Discuz!的代碼,形成了如下備份數據庫的方法。(在這里感謝Discuz!的開發者)

備份數據庫有兩種方式,一種是只備份數據庫的結構,一種把是結構和所有的數據都備份出來,當然是第二種方法好啦,不過我為了考慮可能的需求就都作啦。

/******  備份數據庫結構 ******//*函數名稱:table2sql()函數功能:把表的結構轉換成為SQL函數參數:$table: 要進行提取的表名返 回 值:返回提取后的結果,SQL集合函數作者:heiyeluren*/function table2sql($table) { global $db; $tabledump = "DROP TABLE IF EXISTS $table;"; $createtable = $db->query("SHOW CREATE TABLE $table"); $create = $db->fetch_row($createtable); $tabledump .= $create[1].";"; return $tabledump;}/****** 備份數據庫結構和所有數據 ******//*函數名稱:data2sql()函數功能:把表的結構和數據轉換成為SQL函數參數:$table: 要進行提取的表名返 回 值:返回提取后的結果,SQL集合函數作者:heiyeluren*/function data2sql($table) { global $db; $tabledump = "DROP TABLE IF EXISTS $table;"; $createtable = $db->query("SHOW CREATE TABLE $table"); $create = $db->fetch_row($createtable); $tabledump .= $create[1].";"; $rows = $db->query("SELECT * FROM $table"); $numfields = $db->num_fields($rows); $numrows = $db->num_rows($rows); while ($row = $db->fetch_row($rows)) {  $comma = "";  $tabledump .= "INSERT INTO $table VALUES(";  for($i = 0; $i < $numfields; $i++)   {   $tabledump .= $comma."'".mysql_escape_string($row[$i])."'";   $comma = ",";  }  $tabledump .= ");"; } $tabledump .= ""; return $tabledump;}/****** 具體實現操作 ******/好,我們既然把代碼都寫出來了,那么我們如何在具體的程序種去實現備份呢,我們看下面的代碼。/* 備份數據庫 */// 注意:我們一下的數據庫操作采用了phplib的DB類// 定義要保存的數據表、前綴、保存到何處$tables = array('us_sort', 'us_download', 'us_article', 'us_guestbook'); //定義要保存的數據表,一個數組$prefix = 'us_';    // 要保存的.sql文件的前綴$saveto = 'server'; // 要保存到什么地方,是本地還是服務器上,默認是服務器$back_mode = 'all'; // 要保存的方式,是全部備份還是只保存數據庫結構$admin = 'heiyeluren'; //管理員名稱$admin_email = '[email protected]';  // 管理員郵箱// 定義數據保存的文件名$local_filename = $prefix.date('Ymd_His').'.sql"';if (!$filename) { $filename = $db_backup_path . $prefix . date('Ymd_His_'). create_check_code(4) . ".sql"; }$filename = $prefix.date(Ymd_His). create_check_ code(6).".sql";      // 保存在服務器上的文件名// 注意后面的create_check_code()函數,這是一個生成隨機碼的函數,詳細可以參考:// http://blog.csdn.net/heiyeshuwu/archive/2005/01/26/268446.aspx// 獲取數據庫結構和數據內容foreach($tables as $table) { if ($back_mode == 'all') { $sqldump .= data2sql($table); } if ($back_mode == 'table') { $sqldump .= table2sql($table); }}// 如果數據內容不是空就開始保存if(trim($sqldump)) { // 寫入開頭信息 $sqldump =   "# --------------------------------------------------------".  "# 數據表備份".  "#".  "# 服務器: $db->Host".  "# 數據庫:$db->Database".  "# 備份編號: ". create_sess_id() ."". // 這里有一個生成session id的函數  "# 備份時間: ".time_to_date('',6)."". // 這里就是獲取當前時間的函數  "#".  "# 管理員:$admin ($admin_email)". // 管理員的用戶名和郵箱地址  "# $copyright".  "# --------------------------------------------------------".  $sqldump;  // 保存到本地 if($saveto == "local")  {  ob_end_clean();  header('Content-Encoding: none');  header('Content-Type: '.(strpos($HTTP_SERVER_VARS['HTTP_USER_AGENT'], 'MSIE') ? 'application/octetstream' : 'application/octet-stream'));  header('Content-Disposition: '.(strpos($HTTP_SERVER_VARS['HTTP_USER_AGENT'], 'MSIE') ? 'inline; ' : 'attachment; ').'filename="'.$local_filename);  header('Content-Length: '.strlen($sqldump));  header('Pragma: no-cache');  header('Expires: 0');  echo $sqldump; }  // 保存到本地結束  // 保存在服務器 if($saveto == "server")  {  if($filename != "")   {   @$fp = fopen($filename, "w+");   if ($fp)   {    @flock($fp, 3);    if(@!fwrite($fp, $sqldump))     {     @fclose($fp);     exit_msg("數據文件無法保存到服務器,請檢查目錄屬性你是否有寫的權限。");    }     else     {     exit_msg("數據成功備份至服務器 $filename 中。");    }   }   else   {    exit_msg("無法打開你指定的目錄". $filename .",請確定該目錄是否存在,或者是否有相應權限");    }  }   else   {   exit_msg("您沒有輸入備份文件名,請返回修改。");  } } // 保存到服務器結束}else{ exit_msg("數據表沒有任何內容");}/* 備份數據庫結束 */

呵呵,基本上這樣就結束了,然后涉及到的一個問題是如何把數據恢復到數據庫中,我想這個是不復雜的,但是最好能夠滿足有從客戶端和從服務器恢復數據的功能。

作者:http://www.zhujiangroad.com
來源:http://www.zhujiangroad.com
北斗有巢氏 有巢氏北斗