基于thinkphp的数据库在线备份还原

网站技术 ayflying 1633℃ 评论

搜索了不少资料,东拼西凑总算完成了。下面贴出来代码,原理就不讲解了,代码挺简单的,重要部分我都做了注释。

<?php
use Think\Db;
 /**
 * 数据库备份还原类
 * @author luoe.cn<[email protected]>
 * @date 2016-04-29
 * Class BackupDb
 */
class BackupDb{
	private $handler;
    
	private $config = array(
        'host' => '127.0.0.1',
        'port' => 3306,
        'user' => '',
        'password' => '',
        'database' => '',
        'charset' => 'UTF8',
    );
	
    private $filename = "./db/";
    private $tables = array();
    private $error;
    private $begin; //开始时间
	
	/**
     * 架构方法
     * @param array $config
     */
	 
    public function __construct($filename)
    {
		$this -> filename = $filename;
        $this ->config['host'] = C('DB_HOST');
        $this ->config['port'] = C('DB_PORT');
        $this ->config['user'] = C('DB_USER');
        $this ->config['password'] = C('DB_PWD');
        $this ->config['database'] = C('DB_NAME');
        $this ->config['charset'] = C('DB_CHARSET');
        
		$this->begin = microtime(true);
		
        
	}
	
	
	/**
     * 备份
     * @param array $tables
     * @return bool
     */
    public function backup($tables = array())
    {
		//存储表定义语句的数组
		$ddl = array();
		//存储数据的数组
		$data = array();
		$this->setTables($tables);
        if (!empty($this->tables))
        {
            foreach ($this->tables as $table)
            {
				$ddl[] = $this->getDDL($table);
				$data[] = $this->getData($table);
            }
			
            //开始写入
            $r = $this->writeToFile($this->tables, $ddl, $data);
			return $r;
        }
        else
        {
            $this->error = '数据库中没有表!';
            return false;
        }
    }
 
    /**
     * 设置要备份的表
     * @param array $tables
     */
    private function setTables($tables = array())
    {
		
        if (!empty($tables) && is_array($tables))
        {
            //备份指定表
            $this->tables = $tables;
        }
        else
        {
            //备份全部表
            $this->tables = $this->getTables();
        }
    }
 
    /**
     * 查询
     * @param string $sql
     * @return mixed
     */
    private function query($sql = '')
    {
		
	$list = M() -> query($sql);
        return $list;
    }
 
    /**
     * 获取全部表
     * @return array
     */
    private function getTables()
    {
		
		$sql = 'SHOW TABLES';
        $list = $this->query($sql);
		$tables = array();
		foreach ($list as $value)
        {
			$tables[] =  current($value);
        }
		
		return $tables;
		}
 
    /**
     * 获取表定义语句
     * @param string $table
     * @return mixed
     */
    private function getDDL($table = '')
    {
		
	$sql = "SHOW CREATE TABLE `{$table}`";
        $ddl = $this->query($sql);
	$ddl = $ddl[0]['create table'].";";
	return $ddl;
    }
 
    /**
     * 获取表数据
     * @param string $table
     * @return mixed
     */
    private function getData($table = '')
    {
        $sql = "SHOW COLUMNS FROM `{$table}`";
        $list = $this->query($sql);
        //字段
        
        $data = $this->query("SELECT * FROM `{$table}`");
        foreach ($data as $value)
        {
            $dataSql = '';
            foreach ($value as $v)
            {
                $dataSql .= "'" . mysql_escape_string ( $v ) . "',";
            }
            $dataSql = substr($dataSql, 0, -1);
            $query .= "INSERT INTO `{$table}` VALUES ({$dataSql});\r\n";
			
        }
        return $query;
    }
 
    /**
     * 写入文件
     * @param array $tables
     * @param array $ddl
     * @param array $data
     */
    private function writeToFile($tables = array(), $ddl = array(), $data = array())
    {
        $str = "/*\r\nMySQL Database Backup Tools\r\n";
        $str .= "Server:{$this->config['host']}:{$this->config['port']}\r\n";
        $str .= "Database:{$this->config['database']}\r\n";
        $str .= "Data:" . date('Y-m-d H:i:s', time()) . "\r\n*/\r\n";
        $str .= "SET FOREIGN_KEY_CHECKS=0;\r\n";
        $i = 0;
        foreach ($tables as $table)
        {
            $str .= "-- ----------------------------\r\n";
            $str .= "-- Table structure for {$table}\r\n";
            $str .= "-- ----------------------------\r\n";
            $str .= "DROP TABLE IF EXISTS `{$table}`;\r\n";
            $str .= $ddl[$i] . "\r\n";
            $str .= "-- ----------------------------\r\n";
            $str .= "-- Records of {$table}\r\n";
            $str .= "-- ----------------------------\r\n";
            $str .= $data[$i] . "\r\n";
            $i++;
        }
		$filename = $this -> filename."backup_".time().".sql";
        $r = file_put_contents($filename, $str) ? '备份成功!花费时间' . (microtime(true) - $this->begin) . 'ms' : '备份失败!';
		return $r;
	}
 
    /**
     * 错误信息
     * @return mixed
     */
    public function getError()
    {
        return $this->error;
    }
	
	/**
	*	数据库还原
	*	@param string $path
	*/
    public function restore($path = '')
    {
		$path = $this -> filename.$path;
		//return $path;
		
        if (!file_exists($path))
        {
            $this->error = 'SQL文件不存在!';
            return false;
        }
        else
        {
            $sql = $this->ParseSqlArr($path);
            try
            {
			
        	foreach($sql as $val){
		M() -> execute($val);	//循环写入数据库 
            }
				
	    $r = '还原成功!花费时间'. (microtime(true) - $this->begin) . 'ms';
	    return $r;
	}catch (PDOException $e){
                $this->error = $e->getMessage();
                return false;
        }
        }
		
    }
 
 
	
    /**
     * 解析SQL文件为SQL语句数组
     * @param string $path
     * @return array|mixed|string
     */
    private function ParseSqlArr($sqlfile){
		// sql文件包含的sql语句数组
		$sqls = array ();
		$f = fopen ( $sqlfile, "rb" );
		// 创建表缓冲变量
		$create = '';
		while ( ! feof ( $f ) ) {
			// 读取每一行sql
			$line = fgets ( $f );
			// 如果包含'-- '等注释,或为空白行,则跳过
			if (trim ( $line ) == '' || preg_match ( '/^--*?/', $line, $match )) {
				continue;
			}
			// 如果结尾包含';'(即为一个完整的sql语句,这里是插入语句),并且不包含'ENGINE='(即创建表的最后一句),
			if (! preg_match ( '/;/', $line, $match ) || preg_match ( '/ENGINE=/', $line, $match )) {
				// 将本次sql语句与创建表sql连接存起来
				$create .= $line;
				// 如果包含了创建表的最后一句
				
				if (preg_match ( '/ENGINE=/', $create, $match )) {
					// 则将其合并到sql数组
					$create = preg_replace('/\/\*[^\*\/]*\*\//i', "", $create);//删除多行注释
					$sqls [] = $create;
					// 清空当前,准备下一个表的创建
					$create = '';
				}
				// 跳过本次
				continue;
			}
			$sqls [] = $line;
		}
		fclose ( $f );
		return $sqls;
	}
	
}


转载请注明:七彩悠悠博客 | 心悠悠 情悠悠 » 基于thinkphp的数据库在线备份还原

高效,专业,悠悠博客

联系我们