首頁  >  文章  >  php教程  >  数据库备份与恢复

数据库备份与恢复

WBOY
WBOY原創
2016-06-07 11:44:311103瀏覽

一个thinkphp操作类,用来导出mysql数据和导入备份
数据库备份与恢复<?php <br /> class DBAction extends CommonAction{<br>     private $ds = "\n\r\n\r";<br>     // 每条sql语句的结尾符<br>     public $sqlEnd = ";";<br>     public function index(){<br>         $M = M();<br>         $tabs = $M->query('SHOW TABLE STATUS');<br>         $total = 0;<br>         foreach ($tabs as $k => $v) {<br>             $tabs[$k]['size'] = byteFormat($v['Data_length'] + $v['Index_length']);<br>             $total+=$v['Data_length'] + $v['Index_length'];<br>         }<br>         //echo __APP__."/Public/data/";<br>    // echo  $this->export($tablename="");<br>  //  echo $this->restore("./Public/backup/20130704091642_tao_group_v1.sql");<br>         $this->assign("list", $tabs);<br>         $this->assign("total", byteFormat($tota ));<br>         $this->assign("tables", count($tabs));<br>         $this->display();<br>     }<br>     public function import(){<br>         //echo C("DB_BACKUP");<br>         //print_r(glob(C("DB_BACKUP")."*.sql"))<br>         foreach (glob(C("DB_BACKUP")."*.sql") as $filename) {<br>     $arr[]=array("filename"=>$filename,"size"=>filesize($filename));<br>  }<br> // if(!empty($_GET["file"])){<br> //     $this->restore(I("file"));<br> // }<br>         $this->assign("list", $arr);<br>      $this->display();    <br>     }<br>     public function truncate(){<br>         $table=I("table");<br>         if(!empty($table)){<br>         $M = M();<br>          $result = $M->query('TRUNCATE TABLE '.$table);<br>        <br>         if(empty($result)){<br>             $this->success("清空表成功!");<br>         }else{<br>             $this->error("清空表失败!");<br>           }<br>         }<br>     }<br>     public function delete(){<br>         $table=I("table");<br>         if(!empty($table)){<br>         $M = M();<br>          $result = $M->query('DROP TABLE '.$table);<br>        <br>         if($result){<br>             $this->success("删除表成功!");<br>         }else{<br>             $this->error("删除表失败!");<br>           }<br>         }<br>     }<br>     /**<br>      * getTables 获取数据库表列表<br>      * @return array $tables      返回结果数组    <br>      */<br>     public function getTables() {<br>         $M = M();<br>         $res = $M->query ( "SHOW TABLES;" );<br>         $tables = array ();<br>         foreach ( $res as $row ) {<br>             <br>             foreach ($row as $v){<br>                 $tables[]=$v;<br>             }<br>         }<br>         return $tables;<br>     }<br>     /**<br>      * 插入数据库备份基础信息<br>      *<br>      * @return string<br>      */<br>     private function _base() {<br>         $value = '';<br>         $value .= '-- MySQL database dump' . $this->ds;<br>         $value .= '-- Created by DBAction class, Power By TaoTao. ' . $this->ds;<br>         $value .= '-- http://blog.kisscn.com ' . $this->ds;<br>         $value .= '--' . $this->ds;<br>         $value .= '-- 主机: ' . $this->host . $this->ds;<br>         $value .= '-- 生成日期: ' . date ( 'Y' ) . ' 年  ' . date ( 'm' ) . ' 月 ' . date ( 'd' ) . ' 日 ' . date ( 'H:i' ) . $this->ds;<br>         $value .= '-- MySQL版本: ' . mysql_get_server_info () . $this->ds;<br>         $value .= '-- PHP 版本: ' . phpversion () . $this->ds;<br>         $value .= $this->ds;<br>         $value .= '--' . $this->ds;<br>         $value .= '-- 数据库: `' . C("DB_NAME") . '`'. $this->ds;<br>         $value .= '--' . $this->ds ;<br>         $value .= '-- -------------------------------------------------------';<br>         $value .= $this->ds . $this->ds;<br>         return $value;<br>     }<br>     /**<br>      * 插入表结构<br>      *<br>      * @param unknown_type $table            <br>      * @return string<br>      */<br>     private function _insert_table_structure($table) {<br>         $sql = '';<br>         $sql .= "--" . $this->ds;<br>         $sql .= "-- 表的结构" . $table .$this->ds."--" .$this->ds;<br>          $M = M();<br>         // 如果存在则删除表<br>         $sql .= "DROP TABLE IF EXISTS `" . $table . '`' . $this->sqlEnd . $this->ds;<br>         // 获取详细表信息<br>         $res = $M->query ( 'SHOW CREATE TABLE `' . $table . '`' );<br>         $sql .= $res [0]["Create Table"];<br>         $sql .= $this->sqlEnd . $this->ds;<br>         // 加上<br>         $sql .= $this->ds;<br>         $sql .= "--" . $this->ds;<br>         $sql .= "-- 转存表中的数据 " . $table . $this->ds;<br>         $sql .= "--" . $this->ds;<br>         $sql .= $this->ds;<br>         return $sql;<br>     }<br> <br>     /**<br>      * 插入语句构造<br>      *<br>      * @param string $table                     <br>      * @return string<br>      */<br>     private function _insert_record($table) {<br>         // sql字段逗号分割<br> <br>         $M=M();<br>         $res = $M->query ( 'select * FROM `' . $table . '`' );    <br>         // 循环每个子段下面的内容<br>             foreach ($res as $val){<br>         $comma = 0;<br>                 $insert .= "INSERT INTO `" . $table . "` VALUES(";<br>                 foreach ($val as $v){<br>         $insert.=$comma == 0 ? "" : ",";<br>             $insert.= ( "'" . mysql_escape_string ( $v ) . "'");<br>                         $comma++;<br>             <br>             }<br>             $insert .= ");" . $this->ds;<br>             <br>     }<br>         <br>         return $insert;<br>     }<br> <br>     /**<br>      * 写入文件<br>      *<br>      * @param string $sql            <br>      * @param string $filename            <br>      * @param string $dir            <br>      * @return boolean<br>      */<br>     private function _write_file($sql, $filename, $dir) {<br>           $dir = C("DB_BACKUP");<br>         // 创建目录<br>         if (! is_dir ( $dir )) {<br>             mkdir ( $dir, 0777, true );<br>         }<br>         $re = true;<br>         if (! @$fp = fopen ( $dir . $filename, "w+" )) {<br>             $re = false;<br>             $msg .= "打开文件失败!";<br>         }<br>         if (! @fwrite ( $fp, $sql )) {<br>             $re = false;<br>             $msg .= "写入文件失败,请文件是否可写";<br>         }<br>         if (! @fclose ( $fp )) {<br>             $re = false;<br>             $msg .= "关闭文件失败!";<br>         }<br>         return $re;<br>     }<br>     /**<br>      * 数据库备份<br>      * 参数:备份哪个表(可选),备份目录(可选,默认为backup),分卷大小(可选,默认2048,即2M)<br>      *<br>      * @param string $dir            <br>      * @param int $size            <br>      * @param array $tablename            <br>      */<br>     public function export() {<br>         $tablename=I("table");<br>          $dir = C("DB_BACKUP");<br>         // 创建目录<br>         if (! is_dir ( $dir )) {<br>             mkdir ( $dir, 0777, true ) or die ( '创建文件夹失败' );<br>         }<br>         $size = C("DB_BACKUP_SIZE");<br>         $sql = '';<br>         $tables=explode(",", $tablename);<br>         //print_r($tables);<br>         $M=M();<br>         if(!empty($tablename)){<br>         foreach ($tables as $value) {<br>             $msg .= '正在备份表' . $value . '<br>';<br>             // 插入文件头信息<br>             $sql = $this->_base ();<br>             // 插入表结构信息<br>             $sql .= $this->_insert_table_structure ( $value );<br>             // 文件名前缀<br>             $filename = date ( 'YmdHis' ) . "_" . $value;<br>             // 分卷标识<br>             $p = 1;<br>             $sql .= $this->_insert_record ( $value);<br>                         // 如果大于分卷大小,则写入文件<br>                         //$msg.="文件大小为:".strlen ( $sql );<br>                 if (strlen ( $sql ) >= $size * 1024) {<br>                     $file = $filename . "_v" . $p . ".sql";<br>                     if ($this->_write_file ( $sql, $file, $dir )) {<br>                         $msg .= "表-" . $value . "-卷-" . $p . '<br>';<br>                         $msg.= "-数据备份完成,生成备份文件 <span>$dir$filename</span><br>";<br>                     } else {<br>                         $msg .= "备份表-" . $value . "-失败<br>";<br>                         return false;<br>                     }<br>                     // 下一个分卷<br>                     $p ++;<br>                     // 重置$sql变量为空,重新计算该变量大小<br>                     $sql = "";<br>                 }else{<br>                             // sql大小不够分卷大小<br>             if ($sql != "") {<br>                 $filename .=  ".sql";<br>                 if ($this->_write_file ( $sql, $filename, $dir )) {<br>                     $msg .= "表-" . $value . "-卷-" . $p. '<br>'. "-数据备份完成,生成备份文件 <span>$dir$filename</span><br>";<br>                 } else {<br>                     $msg .= "备份卷-" . $p . "-失败<br>";<br>                     return false;<br>                 }<br>             }<br>                 }<br>         }<br>         }else{<br>                     // 备份全部表<br>             if ($tables = $M->query( "show table status from " . C("DB_NAME") )) {<br>                 $msg .= "读取数据库结构成功!<br>";<br>             } else {<br>                 exit ( "读取数据库结构失败!<br>" );<br>             }<br>             // 插入dump信息<br>             $sql .= $this->_base ();<br>             // 文件名前面部分<br>             $filename = date ( 'YmdHis' ) . "_all";<br>             // 查出所有表<br>             $tables = $M->query ( 'SHOW TABLES' );<br>             // 第几分卷<br>             $p = 1;<br>             // 循环所有表<br>             foreach  ( $tables as $value) {<br>                 foreach ($value as $v) {<br>                 <br>                 // 获取表结构<br>                 $sql .= $this->_insert_table_structure ( $v );<br>                     // 单条记录<br>                     $sql .= $this->_insert_record ( $v );<br>                   }<br> <br>             }<br>                   // 如果大于分卷大小,则写入文件<br>                     if (strlen ( $sql ) >= $size * 1024) {<br> <br>                         $file = $filename . "_v" . $p . ".sql";<br>                         // 写入文件<br>                         if ($this->_write_file ( $sql, $file, $dir )) {<br>                             $this->msg .= "-卷-" . $p . "-数据备份完成,生成备份文件<span>$dir$file</span><br>";<br>                         } else {<br>                             $this->msg .= "备份卷-" . $p . "-失败<br>";<br>                             return false;<br>                         }<br>                         // 下一个分卷<br>                         $p ++;<br>                         // 重置$sql变量为空,重新计算该变量大小<br>                         //$sql = "";<br>                     }<br>                 // sql大小不够分卷大小<br>             if ($sql != "") {<br>                 $filename .=  ".sql";<br>                 if ($this->_write_file ( $sql, $filename, $dir )) {<br>                     $msg .= "数据库-" . C("DB_NAME") . "-卷-" . $p. '<br>'. "-数据备份完成,生成备份文件 <span>$dir$filename</span><br>";<br>                 } else {<br>                     $msg .= "备份卷-" . $p . "-失败<br>";<br>                     return false;<br>                 }<br>             }<br>         }<br>         echo $msg; <br>     }<br> <br>     /**<br>      * 导入备份数据<br>      * 说明:分卷文件格式20120516211738_all_v1.sql<br>      * 参数:文件路径(必填)<br>      *<br>      * @param string $sqlfile            <br>      */<br>     function restore($file) {<br>         $sqlfile=C("DB_BACKUP").$file;<br> <br>         // 检测文件是否存在<br>         if (! file_exists ( $sqlfile )) {<br>             exit ( "文件不存在!请检查" );<br>         }<br>         $this->lock ( C("DB_NAME") );<br>         // 获取数据库存储位置<br>         $sqlpath = pathinfo ( $sqlfile );<br>     //    $this->sqldir = $sqlpath ['dirname'];<br>         // 检测是否包含分卷,将类似20120516211738_all_v1.sql从_v分开,有则说明有分卷<br>         $volume = explode ( "_v", $sqlfile );<br>         $volume_path = $volume [0];<br>         $msg .= "请勿刷新及关闭浏览器以防止程序被中止,如有不慎!将导致数据库结构受损<br>";<br>         $msg .= "正在导入备份数据,请稍等!<br>";<br>         if (empty ( $volume [1] )) {<br>              $msg .= "正在导入sql:<span>" . $sqlfile . '</span><br>';<br>             // 没有分卷<br>             if ($this->_import ( $sqlfile )) {<br>             echo    $msg .= "数据库导入成功!";<br>         //$this->success("数据库导入成功!");<br>             } else {<br>                 exit ( '数据库导入失败!' );<br>             }<br>         } else {<br>             // 存在分卷,则获取当前是第几分卷,循环执行余下分卷<br>             $volume_id = explode ( ".sq", $volume [1] );<br>             // 当前分卷为$volume_id<br>             $volume_id = intval ( $volume_id [0] );<br>             while ( $volume_id ) {<br>                 $tmpfile = $volume_path . "_v" . $volume_id . ".sql";<br>                 // 存在其他分卷,继续执行<br>                 if (file_exists ( $tmpfile )) {<br>                     // 执行导入方法<br>                     $msg .= "正在导入分卷 $volume_id :<span>" . $tmpfile . '</span><br>';<br>                     if ($this->_import ( $tmpfile )) {<br> <br>                     } else {<br>                         $volume_id = $volume_id ? $volume_id :1;<br>                         exit ( "导入分卷:<span>" . $tmpfile . '</span>失败!可能是数据库结构已损坏!请尝试从分卷1开始导入' );<br>                     }<br>                 } else {<br>                     $msg .= "此分卷备份全部导入成功!<br>";<br>                     echo $msg;<br>                 }<br>                 $volume_id ++;<br>             }<br>         }<br>     }<br>     /**<br>      * 将sql导入到数据库(普通导入)<br>      *<br>      * @param string $sqlfile            <br>      * @return boolean<br>      */<br>     private function _import($sqlfile) {<br>         // sql文件包含的sql语句数组<br>         $sqls = array ();<br>         $f = fopen ( $sqlfile, "rb" );<br>         // 创建表缓冲变量<br>         $create_table = '';<br>         while ( ! feof ( $f ) ) {<br>             // 读取每一行sql<br>             $line = fgets ( $f );<br>             // 这一步为了将创建表合成完整的sql语句<br>             // 如果结尾没有包含';'(即为一个完整的sql语句,这里是插入语句),并且不包含'ENGINE='(即创建表的最后一句)<br>             if (! preg_match ( '/;/', $line ) || preg_match ( '/ENGINE=/', $line )) {<br>                 // 将本次sql语句与创建表sql连接存起来<br>                 $create_table .= $line;<br>                 // 如果包含了创建表的最后一句<br>                 if (preg_match ( '/ENGINE=/', $create_table)) {<br>                     //执行sql语句创建表<br>                     $this->_insert_into($create_table);<br>                     // 清空当前,准备下一个表的创建<br>                     $create_table = '';<br>                 }<br>                 // 跳过本次<br>                 continue;<br>             }<br>             //执行sql语句<br>             $this->_insert_into($line);<br>         }<br>         fclose ( $f );<br>         return true;<br>     }<br>     //插入单条sql语句<br>     private function _insert_into($sql){<br>         $M=M();<br>         if (! $M->query( trim ( $sql ) )) {<br>             $msg .= mysql_error ();<br>             return false;<br>         }<br>     }<br>         // 锁定数据库,以免备份或导入时出错<br>     private function lock($tablename, $op = "WRITE") {<br>         $M=M();<br>         if ($M->query( "lock tables " . $tablename . " " . $op ))<br>             return true;<br>         else<br>             return false;<br>     }<br> <br>     // 解锁<br>     private function unlock() {<br>         $M=M();<br>         if ($M->query ( "unlock tables" ))<br>             return true;<br>         else<br>             return false;<br>     }<br>     <br> }<br> /**<br>  +----------------------------------------------------------<br>  * 功能:计算文件大小<br>  +----------------------------------------------------------<br>  * @param int $bytes<br>  +----------------------------------------------------------<br>  * @return string 转换后的字符串<br>  +----------------------------------------------------------<br>  */<br> function byteFormat($bytes) {<br>     $sizetext = array(" B", " KB", " MB", " GB", " TB", " PB", " EB", " ZB", " YB");<br>     return round($bytes / pow(1024, ($i = floor(log($bytes, 1024)))), 2) . $sizetext[$i];<br> }    备份效果:
数据库备份与恢复

AD:真正免费,域名+虚机+企业邮箱=0元

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn