首页 > 语言 > PHP > 正文

php类实现MySQL数据库备份、还原

2024-09-04 11:44:13
字体:
来源:转载
供稿:网友

这是一个非常简单的利用php来备份mysql数据库的类文件,我们只要简单的在dbmange中配置好连接地址用户名与数据库即可,下面我们一起来看这个例子,代码如下:

  1. <?php   
  2. /**  
  3.  * 创建时间: 2012年5月21日  
  4.  *  
  5.  * 说明:分卷文件是以_v1.sql为结尾(20120522021241_all_v1.sql)  
  6.  * 功能:实现mysql数据库分卷备份,选择表进行备份,实现单个sql文件及分卷sql导入  
  7.  * 使用方法:  
  8.  *  
  9.  * ------1. 数据库备份(导出)------------------------------------------------------------  
  10. //分别是主机,用户名,密码,数据库名,数据库编码  
  11. $db = new DBManage ( 'localhost', 'root', 'root', 'test', 'utf8' );  
  12. // 参数:备份哪个表(可选),备份目录(可选,默认为backup),分卷大小(可选,默认2000,即2M)  
  13. $db->backup ();  
  14.  * ------2. 数据库恢复(导入)------------------------------------------------------------  
  15. //分别是主机,用户名,密码,数据库名,数据库编码  
  16. $db = new DBManage ( 'localhost', 'root', 'root', 'test', 'utf8' );  
  17. //参数:sql文件  
  18. $db->restore ( './backup/20120516211738_all_v1.sql');  
  19.  *----------------------------------------------------------------------  
  20.  */  
  21. class DBManage   
  22. {   
  23.     var $db// 数据库连接   
  24.     var $database// 所用数据库   
  25.     var $sqldir// 数据库备份文件夹   
  26.     var $record;   
  27.     // 换行符   
  28.     private $ds = "n";   
  29.     // 存储SQL的变量   
  30.     public $sqlContent = "";   
  31.     // 每条sql语句的结尾符   
  32.     public $sqlEnd = ";";   
  33.     /**  
  34.      * 初始化  
  35.      *  
  36.      * @param string $host  
  37.      * @param string $username  
  38.      * @param string $password  
  39.      * @param string $thisatabase  
  40.      * @param string $charset  
  41.      */  
  42.     function __construct($host = 'localhost'$username = 'root'$password = ''$thisatabase = 'test'$charset = 'utf8')   
  43.     {   
  44.         $this->host = $host;   
  45.         $this->username = $username;   
  46.         $this->password = $password;   
  47.         $this->database = $thisatabase;   
  48.         $this->charset = $charset;   
  49.         // 连接数据库   
  50.         $this->db = mysql_connect ( $this->host, $this->username, $this->password ) or die ( "数据库连接失败." );   
  51.         // 选择使用哪个数据库   
  52.         mysql_select_db ( $this->database, $this->db ) or die ( "无法打开数据库" );   
  53.         // 数据库编码方式   
  54.         mysql_query ( 'SET NAMES ' . $this->charset, $this->db );   
  55.     }   
  56.     
  57.     /*  
  58.       * ------------------------------------------数据库备份start----------------------------------------------------------  
  59.       */  
  60.     
  61.     /**  
  62.      * 数据库备份  
  63.      * 参数:备份哪个表(可选),备份目录(可选,默认为backup),分卷大小(可选,默认2000,即2M)  
  64.      *  
  65.      * @param $string $dir  
  66.      * @param int $size  
  67.      * @param $string $tablename  
  68.      */  
  69.     function backup($tablename = ''$dir = ''$size = 2000)   
  70.     {   
  71.         //$dir = $dir ? $dir : 'backup/';   
  72.         //$size = $size ? $size : 2000;   
  73.         $sql = '';   
  74.         // 只备份某个表   
  75.         if (! emptyempty ( $tablename ))   
  76.         {   
  77.             echo '正在备份表' . $tablename . '<br />';   
  78.             // 插入dump信息   
  79.             $sql = $this->_retrieve();   
  80.             // 插入表结构信息   
  81.             $sql .= $this->_insert_table_structure ( $tablename );   
  82.             // 插入数据   
  83.             $data = mysql_query ( "select * from " . $tablename );   
  84.             // 文件名前面部分   
  85.             $filename = date ( 'YmdHis' ) . "_" . $tablename;   
  86.             // 字段数量   
  87.             $num_fields = mysql_num_fields ( $data );   
  88.             // 第几分卷   
  89.             $p = 1;   
  90.             // 循环每条记录   
  91.             while ( $record = mysql_fetch_array ( $data ) )   
  92.             {   
  93.                 // 单条记录   
  94.                 $sql .= $this->_insert_record ( $tablename$num_fields$record );   
  95.                 // 如果大于分卷大小,则写入文件   
  96.                 if (strlen ( $sql ) >= $size * 1000)   
  97.                 {   
  98.                     $file = $filename . "_v" . $p . ".sql";   
  99.                     if ($this->_write_file ( $sql$file$dir ))   
  100.                     {   
  101.                         echo "表-" . $tablename . "-卷-" . $p . "-数据备份完成,生成备份文件 <span style='color:#f00;'>$dir$filename</span><br />";   
  102.                     }   
  103.                     else  
  104.                     {   
  105.                         echo "备份表-" . $tablename . "-失败<br />";   
  106.                     }   
  107.                     // 下一个分卷   
  108.                     $p ++;   
  109.                     // 重置$sql变量为空,重新计算该变量大小   
  110.                     $sql = "";   
  111.                 }   
  112.             }   
  113.             // sql大小不够分卷大小   
  114.             if ($sql != "")   
  115.             {   
  116.                 $filename .= "_v" . $p . ".sql";   
  117.                 if ($this->_write_file ( $sql$filename$dir ))   
  118.                 {   
  119.                     echo "表-" . $tablename . "-卷-" . $p . "-数据备份完成,生成备份文件 <span style='color:#f00;'>$dir$filename</span><br />";   
  120.                 }   
  121.                 else  
  122.                 {   
  123.                     echo "备份卷-" . $p . "-失败<br />";   
  124.                 }   
  125.             }   
  126.         }   
  127.         else  
  128.         { // 备份全部表   
  129.             if ($tables = mysql_query ( "show table status from " . $this->database ))   
  130.             {   
  131.                 echo "读取数据库结构成功!<br />";   
  132.             }   
  133.             else  
  134.             {   
  135.                 exit ( "读取数据库结构成功!<br />" );   
  136.             }   
  137.             // 插入dump信息   
  138.             $sql .= $this->_retrieve();   
  139.             // 文件名前面部分   
  140.             $filename = date ( 'YmdHis' ) . "_all";   
  141.             // 查出所有表   
  142.             $tables = mysql_query ( 'SHOW TABLES' );   
  143.             // 第几分卷   
  144.             $p = 1;   
  145.             // 循环所有表   
  146.             while ( $table = mysql_fetch_array ( $tables ) )   
  147.             {   
  148.                 // 获取表名   
  149.                 $tablename = $table [0];   
  150.                 // 获取表结构   
  151.                 $sql .= $this->_insert_table_structure ( $tablename );   
  152.                 $data = mysql_query ( "select * from " . $tablename );   
  153.                 $num_fields = mysql_num_fields ( $data );   
  154.     
  155.                 // 循环每条记录   
  156.                 while ( $record = mysql_fetch_array ( $data ) )   
  157.                 {   
  158.                     // 单条记录   
  159.                     $sql .= $this->_insert_record ( $tablename$num_fields$record );   
  160.                     // 如果大于分卷大小,则写入文件   
  161.                     if (strlen ( $sql ) >= $size * 1000)   
  162.                     {   
  163.     
  164.                         $file = $filename . "_v" . $p . ".sql";   
  165.                         // 写入文件   
  166.                         if ($this->_write_file ( $sql$file$dir ))   
  167.                         {   
  168.                             echo "-卷-" . $p . "-数据备份完成,生成备份文件<span style='color:#f00;'>$dir$file</span><br />";   
  169.                         }   
  170.                         else  
  171.                         {   
  172.                             echo "备份卷-" . $p . "-失败<br />";   
  173.                         }   
  174.                         // 下一个分卷   
  175.                         $p ++;   
  176.                         // 重置$sql变量为空,重新计算该变量大小   
  177.                         $sql = "";   
  178.                     }   
  179.                 }   
  180.             }   
  181.             // sql大小不够分卷大小   
  182.             if ($sql != "")   
  183.             {   
  184.                 $filename .= "_v" . $p . ".sql";   
  185.                 if ($this->_write_file ( $sql$filename$dir ))   
  186.                 {   
  187.                     echo "-卷-" . $p . "-数据备份完成,生成备份文件 <span style='color:#f00;'>$dir$filename<br />";   
  188.                 }   
  189.                 else  
  190.                 {   
  191.                     echo "备份卷-" . $p . "-失败<br />";   
  192.                 }   
  193.             }   
  194.         }   
  195.     }   
  196.     
  197.     /**  
  198.      * 插入数据库备份基础信息  
  199.      *  
  200.      * @return string  
  201.      */  
  202.     private function _retrieve() {   
  203.         $value = '';   
  204.         $value .= '--' . $this->ds;   
  205.         $value .= '-- MySQL database dump' . $this->ds;   
  206.         $value .= '-- Created by DBManage class, Power By yanue. ' . $this->ds;   
  207.         $value .= '-- http://yanue.net ' . $this->ds;   
  208.         $value .= '--' . $this->ds;   
  209.         $value .= '-- 主机: ' . $this->host . $this->ds;   
  210.         $value .= '-- 生成日期: ' . date ( 'Y' ) . ' 年  ' . date ( 'm' ) . ' 月 ' . date ( 'd' ) . ' 日 ' . date ( 'H:i' ) . $this->ds;   
  211.         $value .= '-- MySQL版本: ' . mysql_get_server_info () . $this->ds;   
  212.         $value .= '-- PHP 版本: ' . phpversion () . $this->ds;   
  213.         $value .= $this->ds;   
  214.         $value .= '--' . $this->ds;   
  215.         $value .= '-- 数据库: `' . $this->database . '`' . $this->ds;   
  216.         $value .= '--' . $this->ds . $this->ds;   
  217.         $value .= '-- -------------------------------------------------------';   
  218.         $value .= $this->ds . $this->ds;   
  219.         return $value;   
  220.     }   
  221.     
  222.     /**  
  223.      * 插入表结构  
  224.      *  
  225.      * @param unknown_type $table  
  226.      * @return string  
  227.      */  
  228.     private function _insert_table_structure($table) {   
  229.         $sql = '';   
  230.         $sql .= "--" . $this->ds;   
  231.         $sql .= "-- 表的结构" . $table . $this->ds;   
  232.         $sql .= "--" . $this->ds . $this->ds;   
  233.     
  234.         // 如果存在则删除表   
  235.         $sql .= "DROP TABLE IF EXISTS `" . $table . '`' . $this->sqlEnd . $this->ds;   
  236.         // 获取详细表信息   
  237.         $res = mysql_query ( 'SHOW CREATE TABLE `' . $table . '`' );   
  238.         $row = mysql_fetch_array ( $res );   
  239.         $sql .= $row [1];   
  240.         $sql .= $this->sqlEnd . $this->ds;   
  241.         // 加上   
  242.         $sql .= $this->ds;   
  243.         $sql .= "--" . $this->ds;   
  244.         $sql .= "-- 转存表中的数据 " . $table . $this->ds;   
  245.         $sql .= "--" . $this->ds;   
  246.         $sql .= $this->ds;   
  247.         return $sql;   
  248.     }   
  249.     
  250.     /**  
  251.      * 插入单条记录  
  252.      *  
  253.      * @param string $table  
  254.      * @param int $num_fields  
  255.      * @param array $record  
  256.      * @return string  
  257.      */  
  258.     private function _insert_record($table$num_fields$record) {   
  259.         // sql字段逗号分割   
  260.         $insert = $comma = "";   
  261.         $insert .= "INSERT INTO `" . $table . "` VALUES(";   
  262.         // 循环每个子段下面的内容   
  263.         for($i = 0; $i < $num_fields$i ++) {   
  264.             $insert .= ($comma . "'" .mysql_real_escape_string ( $record [$i] ) . "'");   
  265.             $comma = ",";   
  266.         }   
  267.         $insert .= ");" . $this->ds;   
  268.         return $insert;   
  269.     }   
  270.     
  271.     /**  
  272.      * 写入文件  
  273.      *  
  274.      * @param string $sql  
  275.      * @param string $filename  
  276.      * @param string $dir  
  277.      * @return boolean  
  278.      */  
  279.     private function _write_file($sql$filename$dir) {   
  280.         $dir = $dir ? $dir : './backup/';   
  281.         // 不存在文件夹则创建   
  282.         if (! file_exists ( $dir )) {   
  283.             mkdir ( $dir );   
  284.         }   
  285.         $re = true;   
  286.         if (! @$fp = fopen ( $dir . $filename"w+" )) {   
  287.             $re = false;   
  288.             echo "打开文件失败!";   
  289.         }   
  290.         if (! @fwrite ( $fp$sql )) {   
  291.             $re = false;   
  292.             echo "写入文件失败,请文件是否可写";   
  293.         }   
  294.         if (! @fclose ( $fp )) {   
  295.             $re = false;   
  296.             echo "关闭文件失败!";   
  297.         }   
  298.         return $re;   
  299.     }   
  300.     
  301.     /*  
  302.       *  
  303.       * -------------------------------上:数据库导出-----------分割线----------下:数据库导入--------------------------------  
  304.       */  
  305.     
  306.     /**  
  307.      * 导入备份数据  
  308.      * 说明:分卷文件格式20120516211738_all_v1.sql  
  309.      * 参数:文件路径(必填)  
  310.      *  
  311.      * @param string $sqlfile  
  312.      */  
  313.     function restore($sqlfile)   
  314.     {   
  315.         // 检测文件是否存在   
  316.         if (! file_exists ( $sqlfile ))   
  317.         {   
  318.             exit ( "文件不存在!请检查" );   
  319.         }   
  320.         $this->lock ( $this->database );   
  321.         // 获取数据库存储位置   
  322.         $sqlpath = pathinfo ( $sqlfile );   
  323.         $this->sqldir = $sqlpath ['dirname'];   
  324.         // 检测是否包含分卷,将类似20120516211738_all_v1.sql从_v分开,有则说明有分卷   
  325.         $volume = explode ( "_v"$sqlfile );   
  326.         $volume_path = $volume [0];   
  327.         echo "请勿刷新及关闭浏览器以防止程序被中止,如有不慎!将导致数据库结构受损<br />";   
  328.         echo "正在导入备份数据,请稍等!<br />";   
  329.         if (emptyempty ( $volume [1] ))   
  330.         {   
  331.             echo "正在导入sql:<span style='color:#f00;'>" . $sqlfile . '</span><br />';   
  332.             // 没有分卷   
  333.             if ($this->_import ( $sqlfile )) {   
  334.                 echo "数据库导入成功!";   
  335.             }   
  336.             else  
  337.             {   
  338.                 exit ( '数据库导入失败!' );   
  339.             }   
  340.         }   
  341.         else  
  342.         {   
  343.             //$volume_id = array();   
  344.             // 存在分卷,则获取当前是第几分卷,循环执行余下分卷   
  345.             $volume_id = explode ( ".sq"$volume [1] );   
  346.             // 当前分卷为$volume_id   
  347.             $volume_id = intval ( $volume_id [0] );   
  348.             while ( $volume_id )   
  349.             {   
  350.                 $tmpfile = $volume_path . "_v" . $volume_id . ".sql";   
  351.                 // 存在其他分卷,继续执行   
  352.                 if (file_exists ( $tmpfile )) {   
  353.                     // 执行导入方法   
  354.                     echo "正在导入分卷<span style='color:#f00;'>" . $tmpfile . '</span><br />';   
  355.                     if ($this->_import ( $tmpfile ))   
  356.                     {   
  357.     
  358.                     }   
  359.                     else  
  360.                     {   
  361.                         exit ( "导入分卷<span style='color:#f00;'>" . $tmpfile . '</span>失败!可能是数据库结构已损坏!请尝试从分卷1开始导入' );   
  362.                     }   
  363.                 }   
  364.                 else  
  365.                 {   
  366.                     echo "此分卷备份全部导入成功!<br />";   
  367.                     return;   
  368.                 }   
  369.                 $volume_id++;   
  370.             }   
  371.         }   
  372.     }   
  373.     
  374.     /**  
  375.      * 将sql导入到数据库(普通导入)  
  376.      *  
  377.      * @param string $sqlfile  
  378.      * @return boolean  
  379.      */  
  380.     private function _import($sqlfile) {   
  381.         // sql文件包含的sql语句数组   
  382.         $sqls = array ();   
  383.         $f = fopen ( $sqlfile"rb" );   
  384.         // 创建表缓冲变量   
  385.         $create = '';   
  386.         while ( ! feof ( $f ) ) {   
  387.             // 读取每一行sql   
  388.             $line = fgets ( $f );   
  389.             // 如果包含'-- '等注释,或为空白行,则跳过   
  390.             if (trim ( $line ) == '' || preg_match ( '/--*?/'$line$match )) {   
  391.                 continue;   
  392.             }   
  393.             // 如果结尾包含';'(即为一个完整的sql语句,这里是插入语句),并且不包含'ENGINE='(即创建表的最后一句),   
  394.             if (! preg_match ( '/;/'$line$match ) || preg_match ( '/ENGINE=/'$line$match )) {   
  395.                 // 将本次sql语句与创建表sql连接存起来   
  396.                 $create .= $line;   
  397.                 // 如果包含了创建表的最后一句   
  398.                 if (preg_match ( '/ENGINE=/'$create$match )) {   
  399.                     // 则将其合并到sql数组   
  400.                     $sqls [] = $create;   
  401.                     // 清空当前,准备下一个表的创建   
  402.                     $create = '';   
  403.                 }   
  404.                 // 跳过本次   
  405.                 continue;   
  406.             }   
  407.             $sqls [] = $line;   
  408.         }   
  409.         fclose ( $f );   
  410.         // 循环sql语句数组,分别执行   
  411.         foreach ( $sqls as $sql ) {   
  412.             str_replace ( "n"""$sql );   
  413.             if (! mysql_query ( trim ( $sql ) )) {   
  414.                 echo mysql_error ();   
  415.                 return false;   
  416.             }   
  417.         }   
  418.         return true;   
  419.     }   
  420.     
  421.     /*  
  422.       * -------------------------------数据库导入end---------------------------------  
  423.       */  
  424.     
  425.     // 关闭数据库连接   
  426.     private function close() {   
  427.         mysql_close ( $this->db );   
  428.     }   
  429.     
  430.     // 锁定数据库,以免备份或导入时出错   
  431.     private function lock($tablename$op = "WRITE") {   
  432.         if (mysql_query ( "lock tables " . $tablename . " " . $op ))   
  433.             return true;   
  434.         else  
  435.             return false;   
  436.     }   
  437.     
  438.     // 解锁   
  439.     private function unlock() {   
  440.         if (mysql_query ( "unlock tables" ))   
  441.             return true;   
  442.         else  
  443.             return false;   
  444.     }   
  445.     
  446.     // 析构   
  447.     function __destruct() {   
  448.         mysql_query ( "unlock tables"$this->db );   
  449.         mysql_close ( $this->db );   
  450.     }  //开源代码Vevb.com 
  451.  
  452. $db = new DBManage ( 'localhost''root''''tao''gbk' );  
  453. //$db->backup ('tao_admin');   
  454. $db->restore ( './backup/20140228222713_tao_admin_v1.sql'); 
  455. ?> 

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表