参照了网上一些文档,最后自己总结写出了两个类,我试了,可以实现数据库备份与上传功能
<?php /** file: dbbackup.class.php 数据库备份类文件,备份文件放在/backup 目录下 package: sql */ date_default_timezone_set('PRC'); //设置时区 class Dbbackup { private $path = "sql/backup/"; //SQL文件保存路径,默认为/backup private $database; //所要备份的数据库的名称 private $size; //分卷分件大小 private $fileName; //SQL文件名 private $ds = "\n"; //换行符 private $sqlEnd = ";"; //每条SQL语句的结尾符号 /** *构造方法,用来实例化备份类对象 *@param string $database 数据库名称,默认值为‘lighting’ *@param int $size 分卷文件大小,默认值为2048 */ function __construct($size = 2048, $database = 'lighting') { $this->database = $database; //设置所要备份的数据库,默认为 lighting $this->size = $size; //分卷文件大小,默认为2MB $this->fileName = date('YmdHis')."_all"; ob_end_flush(); //清除所有缓存 } /** *公用方法,进行数据库备份 *@return bool 是否备份成功 */ public function backup() { $sqlFile = ''; //准备写入数据库的信息 $this->showMess("正在备份"); /*备份指定数据库中所有的数据表*/ if ($tables = mysql_query( "SHOW TABLE STATUS FROM ".$this->database)) { $this->showMess("读取数据库结构成功!"); } else { $this->showMess("读取数据库结构失败!", true); exit(0); } $sqlFile .= $this->retrieve(); //写入头部dump信息 $tables = mysql_query("SHOW TABLES"); //查询数据库中所有的表 $paper = 1; //分卷标示 while($table = mysql_fetch_array($tables)) { $tableName = $table[0]; //获取表名 $sqlFile .= $this->insertTableStructure($tableName); //获取表结构 $data = mysql_query("SELECT * FROM ".$tableName); //获取表中数据 $num_fields = mysql_num_fields($data); /*遍历表中所有数据记录*/ while($record = mysql_fetch_array($data)) { $sqlFile .= $this->insertRecord($tableName, $num_fields, $record); //单条数据记录 /*如果大于分卷大小,则写入文件*/ if($sqlFile >= $this->size*1000) { $file = $this->fileName."_v".$paper.".sql"; //SQL文件名 /*将SQL数据写入文件*/ if($this->writeFile($sqlFile,$file)) { $this->showMess("-卷-<b>".$paper."</b>-数据备份完成,备份文件 [ <span>".$this->path.$file."</span> ]"); } else { $this->showMess("卷-<b>".$paper."</b>-备份失败",true); return false; } /*下一个分卷*/ $paper ++; /*重置$sqlFile变量为空,重新计算该变量大小*/ $sqlFile = ""; } else { /*如果SQL文件没有超过分卷大小,直接写入文件*/ $file = $this->fileName.".sql"; //SQL文件名 if($this->writeFile($sqlFile,$file)) { $this->showMess("-卷-<b>".$paper."</b>-数据备份完成,备份文件 [ <span>".$this->path.$file."</span> ]"); } else { $this->showMess("卷-<b>".$paper."</b>-备份失败",true); return false; } } $this->showMess("恭喜您! <span>备份成功</span>"); } } } /** *类内部调用的私有方法,进行提示信息输出 *@param string $mess 提示信息 *@param bool $err 错误信息标示符,默认为false,true为输出错误信息 */ private function showMess($mess, $err = false) { if($err) $err = "<span>ERROR:</span>"; else $err = ''; echo "<p>".$err.$mess."</p>"; } /** *类内部调用的私有方法,添加数据库备份文件头部基础信息 *@return string $value 头部基础信息 */ private function retrieve() { $value = ''; $value .= '--'.$this->ds; $value .= '-- MySQL database dump'.$this->ds; $value .= '--' . $this->ds; $value .= '-- 主机: '.$_SERVER['SERVER_NAME'].$this->ds; $value .= '-- 生成日期: '.date('Y').'年 '.date('m').'月'.date('d').'日'.date('H:i').$this->ds; $value .= '-- MySQL版本: '.mysql_get_server_info().$this->ds; $value .= '-- PHP 版本: '.phpversion().$this->ds; $value .= $this->ds; $value .= '--'.$this->ds; $value .= '-- 数据库:`'.$this->database.'`'.$this->ds; $value .= '--'.$this->ds.$this->ds; $value .= '-- -------------------------------------------------------'; $value .= $this->ds.$this->ds; return $value; } /** *类内部调用的私有方法,将表结构信息插入 *@param string $tableName 提示信息 *@return string $sqlFileTable 返回表结构 */ private function insertTableStructure($tableName) { $sqlFileTable = ''; $sqlFileTable .= "--".$this->ds; $sqlFileTable .= "-- 表的结构".$tableName.$this->ds; $sqlFileTable .= "--".$this->ds.$this->ds; /*如果数据库中存在此表,进行删除(用户数据库文件导入时)*/ $sqlFileTable .= "DROP TABLE IF EXISTS `".$tableName.'`'.$this->sqlEnd.$this->ds; /*获取详细表信息*/ $res = mysql_query('SHOW CREATE TABLE `'.$tableName.'`'); $row = mysql_fetch_array($res); $sqlFileTable .= $row[1]; $sqlFileTable .= $this->sqlEnd.$this->ds; /*加上表数据提示*/ $sqlFileTable .= $this->ds; $sqlFileTable .= "--".$this->ds; $sqlFileTable .= "-- 转存表中的数据 ".$tableName.$this->ds; $sqlFileTable .= "--".$this->ds; $sqlFileTable .= $this->ds; return $sqlFileTable; } /** *类内部调用的私有方法,将表中的数据插入 *@param string $tableName 表名 *@param int $num_fields 表中数据条数 *@param array $record 表中的数据 *@return string $insert 表中该条数据中所有字段中的数据组成的字符串 */ private function insertRecord($tableName, $num_fields, $record) { $insert = ''; // sql字段逗号分割 $comma = ""; $insert .= "INSERT INTO `".$tableName."` VALUES("; /*循环每个子段下面的内容*/ for($i = 0; $i < $num_fields; $i++) { $insert .= ($comma."'".mysql_real_escape_string($record[$i])."'"); $comma = ","; } $insert .= ");".$this->ds; return $insert; } /** *@param string $sqlFile 所要写入的SQL数据 *@param string $filename SQL备份文件名 *@return bool $re 返回是否成功写入SQL文件 */ private function writeFile($sqlFile, $filename) { $re = true; if (!$fp =fopen($this->path.$filename, "x")) { $re = false; $this->showMess("打开sql文件失败!", true); } if (!fwrite($fp,$sqlFile)) { $re = false; $this->showMess("写入sql文件失败,请文件是否可写", true); } if (!fclose($fp)) { $re = false; $this->showMess("关闭sql文件失败!", true); } return $re; } /*析构函数*/ function __destruct() { echo "再见<br />"; } } ?>
<?php /** file: dbupdata.class.php 数据库更新类文件,将放在/backup 文件下的对应SQL文件更新到数据库 package: sql */ class Dbupdata { private $fileName; //需要上传的文件的名称 private $path = "sql/backup/"; //SQL文件所在路径,默认为/backup private $database; //所要上传到的数据库 /** *构造方法,用来实例化备份类对象 *@param string $fileName SQL文件名称 */ function __construct($fileName) { $this->database = "lighting"; //操作数据库名,默认为lighting $this->fileName = $fileName; } /*公共函数,用于进行数据文件上传*/ public function restore() { if(!file_exists($this->path.$this->fileName)) { $this->showMess("SQL文件不存在! 请检查", true); exit (); } /*检测是否包含分卷,将类似20120516211738_all_v1.sql从_v分开,有则说明有分卷*/ $volume = explode("_v", $this->fileName); $volume_path = $volume[0]; $this->showMess("请勿刷新及关闭浏览器以防止程序被中止,如有不慎!将导致数据库结构受损"); $this->showMess("正在导入备份数据,请稍候!"); /*无分卷sql文件导入*/ if(count($volume) == 1) { $this->showMess("正在导入sql:<span>".$this->fileName.'</span>'); if($this->importInto($this->fileName)) { $this->showMess("数据库导入成功! "); } else { $this->showMess("数据库导入失败!", true); exit(); } } /*有分卷导入*/ else { /*获取当前是第几分卷,循环执行余下分卷*/ $volume_id = explode(".sq", $volume[1]); /*当前分卷为$volume_id*/ $volume_id = intval($volume_id[0]); //将string强制转换为int型 while($volume_id) { $tmpfile = $volume_path."_v".$volume_id.".sql"; //构造当前分卷文件名 /*如果存在分卷就继续执行*/ if(file_exists($this->path.$tmpfile)) { $this->showMess("正在导入分卷".$volume_id.':'.$tmpfile."<br />"); if($this->importInto($tmpfile)) { $this->showMess("分卷".$volume_id.':'.$tmpfile."导入成功!<br />"); } else { $this->showMess("导入分卷<span style='color:#f00;'>".$tmpfile."</span>失败!可能是数据库结构已被破坏,请尝试从分卷一开始导入。", true); } } else { $this->showMess("分卷备份全部导入成功!"); } $volume_id ++; //下一个分卷 } } } /** *类内部调用的私有方法,进行提示信息输出 *@param string $mess 提示信息 *@param bool $err 错误信息标示符,默认为false,true为输出错误信息 */ private function showMess($mess, $err = false) { if($err) $err = "<span>ERROR:</span>"; else $err = ''; echo "<p>".$err.$mess."</p>"; } /** *类内部调用的私有方法,将SQL导入数据库 *@param string $sqlFile 导入的SQL文件名 *@return bool 返回写入是否成功,如果成功则返回true */ private function importInto($sqlFile) { /*读取SQL文件*/ $f = fopen($this->path.$sqlFile, "rb"); /*创建表缓冲变量*/ $create_table = ''; while(!feof($f)) { /*读取每一行sql*/ $line = fgets($f); /*这一步为了将创建表合成完整的sql语句*/ //如果结尾没有包含';'(即为一个完整的sql语句,这里是插入语句),并且不包含'ENGINE='(即创建表的最后一句) if (!preg_match('/;/', $line) || preg_match('/ENGINE=/', $line)) { /*将本次sql语句与创建表sql连接存起来*/ $create_table .= $line; /*如果包含了创建表的最后一句*/ if (preg_match('/ENGINE=/', $create_table)) { /*执行sql语句创建表*/ $this->insertInto($create_table); /*清空当前,准备下一个表的创建*/ $create_table = ''; } /*跳过本次*/ continue; } /*执行sql语句*/ $this->insertInto($line); } fclose ($f); return true; } /** *类内部调用的私有方法,插入单条sql语句 *@return bool 是否插入成功,成功返回true */ private function insertInto($sql){ if (!mysql_query(trim($sql))) { $this->showMess(mysql_error(), true); return false; } } /*析构函数*/ function __destruct() { echo "再见<br />"; } } ?>