php 数据库备份、还原
1 1. mydb.php //DB类 2 2. backup.php //备份脚本 3 3. restore.php //还原脚本 4 5 mydb.php 6 7 <? 8 class db{ 9 10 var $linkid; 11 var $sqlid; 12 var $record; 13 14 function db($host="",$username="",$password="",$database="") 15 { 16 if(!$this->linkid) @$this->linkid = mysql_connect($host, $username, $password) or die("连接服务器失败."); 17 @mysql_select_db($database,$this->linkid) or die("无法打开数据库"); 18 return $this->linkid;} 19 20 function query($sql) 21 {if($this->sqlid=mysql_query($sql,$this->linkid)) return $this->sqlid; 22 else { 23 $this->err_report($sql,mysql_error); 24 return false;} 25 } 26 27 function nr($sql_id="") 28 {if(!$sql_id) $sql_id=$this->sqlid; 29 return mysql_num_rows($sql_id);} 30 31 function nf($sql_id="") 32 {if(!$sql_id) $sql_id=$this->sqlid; 33 return mysql_num_fields($sql_id);} 34 35 function nextrecord($sql_id="") 36 {if(!$sql_id) $sql_id=$this->sqlid; 37 if($this->record=mysql_fetch_array($sql_id)) return $this->record; 38 else return false; 39 } 40 41 function f($name) 42 { 43 if($this->record[$name]) return $this->record[$name]; 44 else return false; 45 } 46 47 function close() {mysql_close($this->linkid);} 48 49 function lock($tblname,$op="WRITE") 50 {if(mysql_query("lock tables ".$tblname." ".$op)) return true; else return false;} 51 52 function unlock() 53 {if(mysql_query("unlock tables")) return true; else return false;} 54 55 function ar() { 56 return @mysql_affected_rows($this->linkid); 57 } 58 59 function i_id() { 60 return mysql_insert_id(); 61 } 62 63 function err_report($sql,$err) 64 { 65 echo "Mysql查询错误<br>"; 66 echo "查询语句:".$sql."<br>"; 67 echo "错误信息:".$err; 68 } 69 /****************************************类结束***************************/ 70 }?> 71 72 backup.php 73 74 <? 75 error_reporting(E_ALL & ~ E_NOTICE); 76 global $mysqlhost, $mysqluser, $mysqlpwd, $mysqldb; 77 $mysqlhost="localhost"; //host name 78 $mysqluser="root"; //login name 79 $mysqlpwd=""; //password 80 $mysqldb=""; //name of database 81 82 include("mydb.php"); 83 $d=new db($mysqlhost,$mysqluser,$mysqlpwd,$mysqldb); 84 /*--------------界面--------------*/if(!$_POST['act']){/*----------------------*/ 85 $msgs[]="服务器备份目录为backup"; 86 $msgs[]="对于较大的数据表,强烈建议使用分卷备份"; 87 $msgs[]="只有选择备份到服务器,才能使用分卷备份功能"; 88 show_msg($msgs); 89 ?> 90 <form name="form1" method="post" action="backup.php"> 91 <table width="99%" border="1" cellpadding='0' cellspacing='1'> 92 <tr align="center" class='header'><td colspan="2">数据备份</td></tr> 93 <tr><td colspan="2">备份方式</td></tr> 94 <tr><td><input type="radio" name="bfzl" value="quanbubiao"> 备份全部数据</td><td>备份全部数据表中的数据到一个备份文件</td></tr> 95 <tr><td><input type="radio" name="bfzl" value="danbiao">备份单张表数据 96 <select name="tablename"><option value="">请选择</option> 97 <? 98 $d->query("show table status from $mysqldb"); 99 while($d->nextrecord()){ 100 echo "<option value='".$d->f('Name')."'>".$d->f('Name')."</option>";} 101 ?> 102 </select></td><td>备份选中数据表中的数据到单独的备份文件</td></tr> 103 <tr><td colspan="2">使用分卷备份</td></tr> 104 <tr><td colspan="2"><input type="checkbox" name="fenjuan" value="yes"> 105 分卷备份 <input name="filesize" type="text" size="10">K</td></tr> 106 <tr><td colspan="2">选择目标位置</td></tr> 107 <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"> 108 备份到本地</td></tr> 109 <tr><td colspan="2" align='center'><input type="submit" name="act" value="备份"></td></tr> 110 </table></form> 111 <?/*-------------界面结束-------------*/}/*---------------------------------*/ 112 /*----*/else{/*--------------主程序-----------------------------------------*/ 113 if($_POST['weizhi']=="localpc"&&$_POST['fenjuan']=='yes') 114 {$msgs[]="只有选择备份到服务器,才能使用分卷备份功能"; 115 show_msg($msgs); pageend();} 116 if($_POST['fenjuan']=="yes"&&!$_POST['filesize']) 117 {$msgs[]="您选择了分卷备份功能,但未填写分卷文件大小"; 118 show_msg($msgs); pageend();} 119 if($_POST['weizhi']=="server"&&!writeable("./backup")) 120 {$msgs[]="备份文件存放目录'./backup'不可写,请修改目录属性"; 121 show_msg($msgs); pageend();} 122 123 /*----------备份全部表-------------*/if($_POST['bfzl']=="quanbubiao"){/*----*/ 124 /*----不分卷*/if(!$_POST['fenjuan']){/*--------------------------------*/ 125 if(!$tables=$d->query("show table status from $mysqldb")) 126 {$msgs[]="读数据库结构错误"; show_msg($msgs); pageend();} 127 $sql=""; 128 while($d->nextrecord($tables)) 129 { 130 $table=$d->f("Name"); 131 $sql.=make_header($table); 132 $d->query("select * from $table"); 133 $num_fields=$d->nf(); 134 while($d->nextrecord()) 135 {$sql.=make_record($table,$num_fields);} 136 } 137 $filename=date("Ymd",time())."_all.sql"; 138 if($_POST['weizhi']=="localpc") down_file($sql,$filename); 139 elseif($_POST['weizhi']=="server") 140 {if(write_file($sql,$filename)) 141 $msgs[]="全部数据表数据备份完成,生成备份文件'./backup/$filename'"; 142 else $msgs[]="备份全部数据表失败"; 143 show_msg($msgs); 144 pageend(); 145 } 146 /*-----------------不要卷结束*/}/*-----------------------*/ 147 /*-----------------分卷*/else{/*-------------------------*/ 148 if(!$_POST['filesize']) 149 {$msgs[]="请填写备份文件分卷大小"; show_msg($msgs);pageend();} 150 if(!$tables=$d->query("show table status from $mysqldb")) 151 {$msgs[]="读数据库结构错误"; show_msg($msgs); pageend();} 152 $sql=""; $p=1; 153 $filename=date("Ymd",time())."_all"; 154 while($d->nextrecord($tables)) 155 { 156 $table=$d->f("Name"); 157 $sql.=make_header($table); 158 $d->query("select * from $table"); 159 $num_fields=$d->nf(); 160 while($d->nextrecord()) 161 {$sql.=make_record($table,$num_fields); 162 if(strlen($sql)>=$_POST['filesize']*1000){ 163 $filename.=("_v".$p.".sql"); 164 if(write_file($sql,$filename)) 165 $msgs[]="全部数据表-卷-".$p."-数据备份完成,生成备份文件'./backup/$filename'"; 166 else $msgs[]="备份表-".$_POST['tablename']."-失败"; 167 $p++; 168 $filename=date("Ymd",time())."_all"; 169 $sql="";} 170 } 171 } 172 if($sql!=""){$filename.=("_v".$p.".sql"); 173 if(write_file($sql,$filename)) 174 $msgs[]="全部数据表-卷-".$p."-数据备份完成,生成备份文件'./backup/$filename'";} 175 show_msg($msgs); 176 /*---------------------分卷结束*/}/*--------------------------------------*/ 177 /*--------备份全部表结束*/}/*---------------------------------------------*/ 178 179 /*--------备份单表------*/elseif($_POST['bfzl']=="danbiao"){/*------------*/ 180 if(!$_POST['tablename']) 181 {$msgs[]="请选择要备份的数据表"; show_msg($msgs); pageend();} 182 /*--------不分卷*/if(!$_POST['fenjuan']){/*-------------------------------*/ 183 $sql=make_header($_POST['tablename']); 184 $d->query("select * from ".$_POST['tablename']); 185 $num_fields=$d->nf(); 186 while($d->nextrecord()) 187 {$sql.=make_record($_POST['tablename'],$num_fields);} 188 $filename=date("Ymd",time())."_".$_POST['tablename'].".sql"; 189 if($_POST['weizhi']=="localpc") down_file($sql,$filename); 190 elseif($_POST['weizhi']=="server") 191 {if(write_file($sql,$filename)) 192 $msgs[]="表-".$_POST['tablename']."-数据备份完成,生成备份文件'./backup/$filename'"; 193 else $msgs[]="备份表-".$_POST['tablename']."-失败"; 194 show_msg($msgs); 195 pageend(); 196 } 197 /*----------------不要卷结束*/}/*------------------------------------*/ 198 /*----------------分卷*/else{/*--------------------------------------*/ 199 if(!$_POST['filesize']) 200 {$msgs[]="请填写备份文件分卷大小"; show_msg($msgs);pageend();} 201 $sql=make_header($_POST['tablename']); $p=1; 202 $filename=date("Ymd",time())."_".$_POST['tablename']; 203 $d->query("select * from ".$_POST['tablename']); 204 $num_fields=$d->nf(); 205 while ($d->nextrecord()) 206 { 207 $sql.=make_record($_POST['tablename'],$num_fields); 208 if(strlen($sql)>=$_POST['filesize']*1000){ 209 $filename.=("_v".$p.".sql"); 210 if(write_file($sql,$filename)) 211 $msgs[]="表-".$_POST['tablename']."-卷-".$p."-数据备份完成,生成备份文件'./backup/$filename'"; 212 else $msgs[]="备份表-".$_POST['tablename']."-失败"; 213 $p++; 214 $filename=date("Ymd",time())."_".$_POST['tablename']; 215 $sql="";} 216 } 217 if($sql!=""){$filename.=("_v".$p.".sql"); 218 if(write_file($sql,$filename)) 219 $msgs[]="表-".$_POST['tablename']."-卷-".$p."-数据备份完成,生成备份文件'./backup/$filename'";} 220 show_msg($msgs); 221 /*----------分卷结束*/}/*--------------------------------------------------*/ 222 /*----------备份单表结束*/}/*----------------------------------------------*/ 223 224 /*---*/}/*-------------主程序结束------------------------------------------*/ 225 226 function write_file($sql,$filename) 227 { 228 $re=true; 229 if(!@$fp=fopen("./backup/".$filename,"w+")) {$re=false; echo "failed to open target file";} 230 if(!@fwrite($fp,$sql)) {$re=false; echo "failed to write file";} 231 if(!@fclose($fp)) {$re=false; echo "failed to close target file";} 232 return $re; 233 } 234 235 function down_file($sql,$filename) 236 { 237 ob_end_clean(); 238 header("Content-Encoding: none"); 239 header("Content-Type: ".(strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') ? 'application/octetstream' : 'application/octet-stream')); 240 241 header("Content-Disposition: ".(strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') ? 'inline; ' : 'attachment; ')."filename=".$filename); 242 243 header("Content-Length: ".strlen($sql)); 244 header("Pragma: no-cache"); 245 246 header("Expires: 0"); 247 echo $sql; 248 $e=ob_get_contents(); 249 ob_end_clean(); 250 } 251 252 function writeable($dir) 253 { 254 255 if(!is_dir($dir)) { 256 @mkdir($dir, 0777); 257 } 258 259 if(is_dir($dir)) 260 { 261 262 if($fp = @fopen("$dir/test.test", 'w')) 263 { 264 @fclose($fp); 265 @unlink("$dir/test.test"); 266 $writeable = 1; 267 } 268 else { 269 $writeable = 0; 270 } 271 272 } 273 274 return $writeable; 275 276 } 277 278 function make_header($table) 279 {global $d; 280 $sql="DROP TABLE IF EXISTS ".$table."\n"; 281 $d->query("show create table ".$table); 282 $d->nextrecord(); 283 $tmp=preg_replace("/\n/","",$d->f("Create Table")); 284 $sql.=$tmp."\n"; 285 return $sql; 286 } 287 288 function make_record($table,$num_fields) 289 {global $d; 290 $comma=""; 291 $sql .= "INSERT INTO ".$table." VALUES("; 292 for($i = 0; $i < $num_fields; $i++) 293 {$sql .= ($comma."'".mysql_escape_string($d->record[$i])."'"); $comma = ",";} 294 $sql .= ")\n"; 295 return $sql; 296 } 297 298 function show_msg($msgs) 299 { 300 $title="提示:"; 301 echo "<table width='100%' border='1' cellpadding='0' cellspacing='1'>"; 302 echo "<tr><td>".$title."</td></tr>"; 303 echo "<tr><td><br><ul>"; 304 while (list($k,$v)=each($msgs)) 305 { 306 echo "<li>".$v."</li>"; 307 } 308 echo "</ul></td></tr></table>"; 309 } 310 311 function pageend() 312 { 313 exit(); 314 } 315 ?> 316 317 restore.php 318 319 <? 320 error_reporting(E_ALL & ~ E_NOTICE); 321 session_start(); 322 global $mysqlhost, $mysqluser, $mysqlpwd, $mysqldb; 323 $mysqlhost="localhost"; //host name 324 $mysqluser="root"; //login name 325 $mysqlpwd=""; //password 326 $mysqldb=""; //name of database 327 328 include("mydb.php"); 329 $d=new db($mysqlhost,$mysqluser,$mysqlpwd,$mysqldb); 330 331 /******界面*/if(!$_POST['act']&&!$_SESSION['data_file']){/**********************/ 332 $msgs[]="本功能在恢复备份数据的同时,将全部覆盖原有数据,请确定是否需要恢复,以免造成数据损失"; 333 $msgs[]="数据恢复功能只能恢复由dShop导出的数据文件,其他软件导出格式可能无法识别"; 334 $msgs[]="从本地恢复数据需要服务器支持文件上传并保证数据尺寸小于允许上传的上限,否则只能使用从服务器恢复"; 335 $msgs[]="如果您使用了分卷备份,只需手工导入文件卷1,其他数据文件会由系统自动导入"; 336 show_msg($msgs); 337 ?> 338 <form action="" method="post" enctype="multipart/form-data" name="restore.php"> 339 <table width="91%" border="0" cellpadding="0" cellspacing="1"> 340 <tr align="center" class="header"><td colspan="2" align="center">数据恢复</td></tr> 341 <tr><td width="33%"><input type="radio" name="restorefrom" value="server" checked> 342 从服务器文件恢复 </td><td width="67%"><select name="serverfile"> 343 <option value="">-请选择-</option> 344 <? 345 $handle=opendir('./backup'); 346 while ($file = readdir($handle)) { 347 if(preg_match("/^[0-9]{8,8}([0-9a-z_]+)(\.sql)$/",$file)) echo "<option value='$file'>$file</option>";} 348 closedir($handle); 349 ?> 350 </select> </td></tr> 351 <tr><td><input type="radio" name="restorefrom" value="localpc"> 从本地文件恢复</td> 352 <td><input type="hidden" name="MAX_FILE_SIZE" value="1500000"><input type="file" name="myfile"></td></tr> 353 <tr><td colspan="2" align="center"> <input type="submit" name="act" value="恢复"></td> </tr></table></form> 354 355 356 <?/**************************界面结束*/}/*************************************/ 357 /****************************主程序*/if($_POST['act']=="恢复"){/**************/ 358 /***************服务器恢复*/if($_POST['restorefrom']=="server"){/**************/ 359 if(!$_POST['serverfile']) 360 {$msgs[]="您选择从服务器文件恢复备份,但没有指定备份文件"; 361 show_msg($msgs); pageend(); } 362 if(!preg_match("/_v[0-9]+/",$_POST['serverfile'])) 363 {$filename="./backup/".$_POST['serverfile']; 364 if(import($filename)) $msgs[]="备份文件".$_POST['serverfile']."成功导入数据库"; 365 else $msgs[]="备份文件".$_POST['serverfile']."导入失败"; 366 show_msg($msgs); pageend(); 367 } 368 else 369 { 370 $filename="./backup/".$_POST['serverfile']; 371 if(import($filename)) $msgs[]="备份文件".$_POST['serverfile']."成功导入数据库"; 372 else {$msgs[]="备份文件".$_POST['serverfile']."导入失败";show_msg($msgs);pageend();} 373 $voltmp=explode("_v",$_POST['serverfile']); 374 $volname=$voltmp[0]; 375 $volnum=explode(".sq",$voltmp[1]); 376 $volnum=intval($volnum[0])+1; 377 $tmpfile=$volname."_v".$volnum.".sql"; 378 if(file_exists("./backup/".$tmpfile)) 379 { 380 $msgs[]="程序将在3秒钟后自动开始导入此分卷备份的下一部份:文件".$tmpfile.",请勿手动中止程序的运行,以免数据库结构受损"; 381 $_SESSION['data_file']=$tmpfile; 382 show_msg($msgs); 383 sleep(3); 384 echo "<script language='javascript'>"; 385 echo "location='restore.php';"; 386 echo "</script>"; 387 } 388 else 389 { 390 $msgs[]="此分卷备份全部导入成功"; 391 show_msg($msgs); 392 } 393 } 394 /**************服务器恢复结束*/}/********************************************/ 395 /*****************本地恢复*/if($_POST['restorefrom']=="localpc"){/**************/ 396 switch ($_FILES['myfile']['error']) 397 { 398 case 1: 399 case 2: 400 $msgs[]="您上传的文件大于服务器限定值,上传未成功"; 401 break; 402 case 3: 403 $msgs[]="未能从本地完整上传备份文件"; 404 break; 405 case 4: 406 $msgs[]="从本地上传备份文件失败"; 407 break; 408 case 0: 409 break; 410 } 411 if($msgs){show_msg($msgs);pageend();} 412 $fname=date("Ymd",time())."_".sjs(5).".sql"; 413 if (is_uploaded_file($_FILES['myfile']['tmp_name'])) { 414 copy($_FILES['myfile']['tmp_name'], "./backup/".$fname);} 415 416 if (file_exists("./backup/".$fname)) 417 { 418 $msgs[]="本地备份文件上传成功"; 419 if(import("./backup/".$fname)) {$msgs[]="本地备份文件成功导入数据库"; unlink("./backup/".$fname);} 420 else $msgs[]="本地备份文件导入数据库失败"; 421 } 422 else ($msgs[]="从本地上传备份文件失败"); 423 show_msg($msgs); 424 /****本地恢复结束*****/}/****************************************************/ 425 /****************************主程序结束*/}/**********************************/ 426 /*************************剩余分卷备份恢复**********************************/ 427 if(!$_POST['act']&&$_SESSION['data_file']) 428 { 429 $filename="./backup/".$_SESSION['data_file']; 430 if(import($filename)) $msgs[]="备份文件".$_SESSION['data_file']."成功导入数据库"; 431 else {$msgs[]="备份文件".$_SESSION['data_file']."导入失败";show_msg($msgs);pageend();} 432 $voltmp=explode("_v",$_SESSION['data_file']); 433 $volname=$voltmp[0]; 434 $volnum=explode(".sq",$voltmp[1]); 435 $volnum=intval($volnum[0])+1; 436 $tmpfile=$volname."_v".$volnum.".sql"; 437 if(file_exists("./backup/".$tmpfile)) 438 { 439 $msgs[]="程序将在3秒钟后自动开始导入此分卷备份的下一部份:文件".$tmpfile.",请勿手动中止程序的运行,以免数据库结构受损"; 440 $_SESSION['data_file']=$tmpfile; 441 show_msg($msgs); 442 sleep(3); 443 echo "<script language='javascript'>"; 444 echo "location='restore.php';"; 445 echo "</script>"; 446 } 447 else 448 { 449 $msgs[]="此分卷备份全部导入成功"; 450 unset($_SESSION['data_file']); 451 show_msg($msgs); 452 } 453 } 454 /**********************剩余分卷备份恢复结束*******************************/ 455 function import($fname) 456 {global $d; 457 $sqls=file($fname); 458 foreach($sqls as $sql) 459 { 460 str_replace("\r","",$sql); 461 str_replace("\n","",$sql); 462 if(!$d->query(trim($sql))) return false; 463 } 464 return true; 465 } 466 function show_msg($msgs) 467 { 468 $title="提示:"; 469 echo "<table width='100%' border='1' cellpadding='0' cellspacing='1'>"; 470 echo "<tr><td>".$title."</td></tr>"; 471 echo "<tr><td><br><ul>"; 472 while (list($k,$v)=each($msgs)) 473 { 474 echo "<li>".$v."</li>"; 475 } 476 echo "</ul></td></tr></table>"; 477 } 478 479 function pageend() 480 { 481 exit(); 482 } 483 ?> 484 485 文件结构非常清晰,只要在文件2和3里面设置好数据库服务器的地址、用户名、密码就可以备份还原数据了。需要注意的是: 486 487 ·使用时候要在同级目录下建一个Backup目录,权限需要可写,用于存放导出的脚本。 488 ·当备份的数据库比较大的时候,服务器脚本超时时间要调大一些。 489 ·支持分卷备份,还原时候只要选择分卷备份的第一个脚本就会自动还原所有的脚本。 490 ·分卷文件大小不要太大,最好不超过2MB。 491 ·安全起见,脚本不用时候记得从服务器上删除。 492 493 494 495 数据库备份 496 1.php备份数据库的原理 497 查找所有表 查找所有字段 查找所有数据 生成SQL 498 2.php中mysql相关函数 499 mysql_list_tables()表查询函数,类似mysql_query()函数 500 mysql_fetch_field()字段信息函数,返回句柄 501 Name字段的名称 502 Table字段所属数据库的名称 503 type 字段的类型 504 max_length字段的最大长度 505 not_null字段是否为空 506 3.备份时注意事项 507 a.注意数据库的大小,过大或者过多分段处理 508 b.生成的SQL文件名或者存在不已被猜到 509 c.备份生成文件可以表或者自动为单位保存 510 d.可以使用ZIP组件压缩生成的文件以便保存 511 $dbname="root" 512 mysql_connect('localhost','root',''); 513 mysql_select_db(); 514 $tq=mysql_list_tables($dbname); 515 while($tr=mysql_fetch_rows($tq)){ 516 517 } 518 function get_table_fd($dbname){ 519 $query=mysql_query("select * from $dbname"); 520 while($row=mysql_fetch_field($query)){ 521 echo $row->name 522 } 523 }