我们常常会因为不小心改错了表中的某些数据而使网站无法正常运行 或 手误删了数据库,这时你就会想到定时备份数据库是有多么的重要~

MySQL_从入门到删库跑路

网上搜了一些关于 用PHP备份MySQL 数据库的,发现几乎都没什么用,所以我就自己写了个。

1.这段代码我们将它命名为:mysql.class.php  的文件里<MySQL数据库操作类>

<?php
/*
*MySQL数据库操作类
*/
if(extension_loaded('mysqli')){
	class DB{
		var $link=null;
		function __construct($db_host,$db_user,$db_pass,$db_name,$db_port){
			$this->link=mysqli_connect($db_host,$db_user,$db_pass,$db_name,$db_port);
			if(!$this->link)die('Connect Error ('.mysqli_connect_errno().') '.mysqli_connect_error());
			mysqli_query($this->link,"set sql_mode = ''");//字符转换,读库
			mysqli_query($this->link,"set character set 'utf8'");//写库
			mysqli_query($this->link,"set names 'utf8'");
			return true;
		}
		function fetch($q){
			return mysqli_fetch_assoc($q);
		}
		function get_row($q){
			$result=mysqli_query($this->link,$q);
			return mysqli_fetch_assoc($result);
		}
		function count($q){
			$result=mysqli_query($this->link,$q);
			$count=mysqli_fetch_array($result);
			return $count['0'];
		}
		function query($q){
			return mysqli_query($this->link,$q);
		}
		function escape($str){
			return mysqli_real_escape_string($this->link,$str);
		}
		function insert($q){
			if(mysqli_query($this->link,$q))
				return mysqli_insert_id($this->link);
			return false;
		}
		function affected(){
			return mysqli_affected_rows($this->link);
		}
		function insert_array($table=null,$array=null){//插入数据
			if(isset($table) && isset($array)){
				$q="INSERT INTO `$table`";
				$q.=" (`".implode("`,`",array_keys($array))."`) ";
				$q.="VALUES ('".implode("','",array_values($array))."') ";
				if(mysqli_query($this->link,$q)){
					return mysqli_insert_id($this->link);
				}else{
					return false;
				}
			}else{
				return false;
			}
		}
		function update_array($table=null,$array=null,$where=null){//更新数据
			/*
      Author: NowTime(初文)
      Email: chenwenzho@aliyun.common
      WriteTime: 2017-01-17 16:03:52
      */
			if($table && $array && $where){
				$qs="UPDATE `$table` SET ";
				$key=array_keys($array);
				$values=array_values($array);
				$q='';
				for($i=0;$i<count($key);$i++){
					$q.="`$key[$i]`='$values[$i]',";
				}
				$qa=$qs.substr($q,0,-1);
				$key=array_keys($where);
				$values=array_values($where);
				$qa.=" WHERE `$key[0]`='$values[0]'";
				if(mysqli_query($this->link,$qa)){
					//return mysqli_insert_id($this->link);
					return $qa;
				}else{
					return false;
				}
			}else{
				return false;
			}
		}
		function error(){
			$error=mysqli_error($this->link);
			$errno=mysqli_errno($this->link);
			return '['.$errno.'] '.$error;
		}
		function close(){
			$q=mysqli_close($this->link);
			return $q;
		}
	}
}else{//we use the old mysql
	class DB{
		var $link=null;
		function __construct($db_host,$db_user,$db_pass,$db_name,$db_port){
			$this->link=@mysql_connect($db_host.':'.$db_port,$db_user,$db_pass);

			if (!$this->link)die('Connect Error (' . mysql_errno() . ') '.mysql_error());
			mysql_select_db($db_name, $this->link) or die(mysql_error($this->link));
			mysql_query("set sql_mode = ''");//字符转换,读库
			mysql_query("set character set 'utf8'");//写库
			mysql_query("set names 'utf8'");
			return true;
		}
		function fetch($q){
			return mysql_fetch_assoc($q);
		}
		function get_row($q){
			$result=mysql_query($q,$this->link);
			return mysql_fetch_assoc($result);
		}
		function count($q){
			$result=mysql_query($q,$this->link);
			$count=mysql_fetch_array($result);
			return $count['0'];
		}
		function query($q){
			return mysql_query($q,$this->link);
		}
		function escape($str){
			return mysql_real_escape_string($str,$this->link);
		}
		function affected(){
			return mysql_affected_rows($this->link);
		}
		function insert($q){
			if(mysql_query($q,$this->link))
				return mysql_insert_id($this->link);
			return false;
		}
		function insert_array($table=null,$array=null){
			if(isset($table) && isset($array)){
				$q="INSERT INTO `$table`";
				$q.=" (`".implode("`,`",array_keys($array))."`) ";
				$q.=" VALUES ('".implode("','",array_values($array))."') ";
				if(mysql_query($q,$this->link)){
					return mysql_insert_id($this->link);
				}else{
					return false;
				}
			}else{
				return false;
			}
		}
		function update_array($table=null,$array=null,$where=null){//更新数据
			/*
      Author: NowTime(初文)
      Email: chenwenzho@aliyun.common
      WriteTime: 2017-01-17 16:03:52
      */
			if($table && $array && $where){
				$qs="UPDATE `$table` SET ";
				$key=array_keys($array);
				$values=array_values($array);
				$q='';
				for($i=0;$i<count($key);$i++){
					$q.="`$key[$i]`='$values[$i]',";
				}
				$qa=$qs.substr($q,0,-1);
				$key=array_keys($where);
				$values=array_values($where);
				$qa.=" WHERE `$key[0]`='$values[0]'";
				if(mysql_query($this->link,$qa)){
					//return mysql_insert_id($this->link);
					return $qa;
				}else{
					return false;
				}
			}else{
				return false;
			}
		}
		function error(){
			$error=mysql_error($this->link);
			$errno=mysql_errno($this->link);
			return '['.$errno.'] '.$error;
		}
		function close(){
			$q=mysql_close($this->link);
			return $q;
		}
	}

}
?>

2.这段代码放到命名为:hunction.php 的文件里<自定义函数>

<?php
function backs_tables($array,$back_path=ROOT){
	@mkdir($back_path);
	global $DB,$db_name,$start_time;
	$now=date('Y年m月d日 H时i分s秒');
	$head="--\n-- 数据库: `$db_name`\n--\n-- 导出日期: `$now`\n--\n\n--\n-- Author: 初文\n--\n-- QQ: 1361289290\n--\n-- blog: https://blog.ogdn.net\n--\n\n";

	$sqls='';
	if($array['0']=='*'){
		$result=$DB->query("SHOW TABLES");
		$count=0;
		while($row=$DB->fetch($result)){
			$count++;
			$sqls.=dataBak($row['Tables_in_test']);
		}
	}else{
		$count=count($array);
		for($i=0;$i<$count;$i++){
			$sqls.=dataBak($array[$i]);
		}
	}
	$foot="\n--\n-- 备份完成,耗时: ".(time()-$start_time)." s, 共计备份 $count 个表, 备份完成时间".date('Y年m月d日 H时i分s秒')."\n--";
	$sql=$head.$sqls.$foot;
	$filename=$db_name."_".date('YmdHis')."_".time()."_".rand(0,9).".sql";//文件名
	$fp=fopen($back_path.$filename,'w');
	fputs($fp,$sql);
	fclose($fp);
	return $foot."\n-- 备份文件大小: ".((strlen($sql)/1024)/1024)." M\n-- 文件绝对路径: ".$back_path."\n--";
}

/**
 * @name 输出数据库结构和所有数据
 * @author 初文, E-mail: chenwenzho@aliyun.com
 * @global $DB
 * @param string $table 数据库表名
 * @return string
 * @version 1.0
 */
function dataBak($table){
	global $DB;

	$sql="DROP TABLE IF EXISTS `$table`;\n";
	$createtable=$DB->query("SHOW CREATE TABLE $table");
	$create=$DB->fetch($createtable);
	$sql.=$create['Create Table'].";\n\n";

	$rows=$DB->query("SELECT * FROM $table");

	while($row=$DB->fetch($rows)){
		$comma='';
		$sql.="INSERT INTO `$table` VALUES(";
		foreach($row as $value){
			$sql.=$comma."'".$value."'";
			$comma=',';
		}
		$sql.=");\n";
	}
	return $sql;
}
?>

3.接下来,这段就是执行备份的代码了(你需要更改这些数据库的信息、访问密钥 和 存放备份文件的 路径),把这段代码把他放到 take_backdata.php 文件里(你也可以把它放到其他命名的文件里)

<?php
$start_time=time();
ini_set('memory_limit','1024M');//加上这两行,可以备份大数据,昨晚测了一下公司的一个600M的表,很快就可以备份成功
ini_set('max_execution_time','0');
define('ROOT',dirname(__FILE__)."/");//定义一个绝对路径,如果用Linux或者windows的计划任务定时执行PHP来执行备份,必须要用绝对路径,相对路径会报错,备份存放放的路径也要使 “绝对路径”!否则会报错
require_once(ROOT."mysql.class.php");//引入MySQL数据库操作类
require_once(ROOT."function.php");//引入自定义函数

$key='1361289290';//访问密钥, 关系到数据的安全, 尽量设置强一点!
$back_path=ROOT."Cache/";//要存放备份数据的位置(即目录地址), 最后面一定要有 / ,现在是保存在本文件(take_backdata.php)所处的路径下的 Cache 文件夹里, 关系到数据的安全, 存放路径最好弄的复杂点
$db_host='127.0.0.1';//数据库连接地址
$db_port=3306;//数据库端口
$db_user='root';//数据库用户名
$db_pass='root';//数据库密码
$db_name='test';//数据库库名

$need_back_tables=Array('*');//需要备份的表,*为全部备份
/**
 * 以Emlog博客程序的数据库表做示例:
 * $need_back_table=Array('*');//需要导出的表,*为全部表都备份
 * $need_back_table=Array('emlog_attachment');//备份 emlog_attachment 这1个表
 * $need_back_table=Array('emlog_attachment','emlog_comment');//备份 emlog_attachment 和 comment 这2个表
 * $need_back_table=Array('emlog_attachment','emlog_comment','emlog_options');//备份 emlog_attachment 、 comment 和 options 这3个表
 * ...以此类推
 */

if(php_sapi_name()==='cgi' || php_sapi_name()==='cli'){//如果是以CGI或CLI运行的PHP, 则可以免输入密码
	$DB=new DB($db_host,$db_user,$db_pass,$db_name,$db_port);//连接数据库
	echo "\nYou are using ".strtoupper(php_sapi_name())." run PHP.\n";
	echo "--\n-- 备份开始: ".date('Y年m月d日 H时i分s秒',$start_time)."\n--\n\n";
	echo backs_tables($need_back_tables,$back_path);//输出备份的结果
}elseif(@$_GET['key']===$key){
	$DB=new DB($db_host,$db_user,$db_pass,$db_name,$db_port);//连接数据库
	header("Content-Type: text/json;Charset=UTF-8");
	echo "--\n-- 备份开始: ".date('Y年m月d日 H时i分s秒',$start_time)."\n--\n\n";
	echo backs_tables($need_back_tables);//输出备份的结果
}else{
	die('你没有访问权限!');
}
?>

配置好后,你就可以访问了,亲测55M左右数据库备份完成耗时 11 秒,以下是本地执行的截图:

本地执行备份截图

以下是命令行执行的结果截图(命令行执行的速度比较快,因为她不用经过Apache/Nginx等解析就可以执行):

命令行执行结果


好了,这下可以添加监控定时执行(http://.../take_backdata.php?key=你设置的访问密钥);或者你用的Linux/Windows服务器可以添加计划任务执行,你可以自己在网上搜相关教程。

本站所用到的文件下载地址:PHP备份MySQL数据库.zip

标签: PHP, MySQL

添加新评论