zoukankan      html  css  js  c++  java
  • 一个不错的MYSQL数据库备份类,PHP版,一个文件,精简版

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