热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

一个PHP文件,高性能的MYSQL数据库备份代码,必备

2016年12月20日亲测,这个类和这段代码绝对没任何问题。主要用于备份线上的数据库,而且用一个PHP文件就搞定了,很方便。重要的事说三遍:已亲测,放心使用。<?

134d0006345f2ea651c7

2016年12月20日亲测,这个类和这段代码绝对没任何问题。 主要用于备份线上的数据库,而且用一个PHP文件就搞定了,很方便。

class DbManage {

var $db; // 数据库连接

var $database; // 所用数据库

var $sqldir; // 数据库备份文件夹

// 换行符

private $ds = &#8220;\n&#8221;;

// 存储SQL的变量

public $sqlCOntent= &#8220;&#8221;;

// 每条sql语句的结尾符

public $sqlEnd = &#8220;;&#8221;;

/**

* 初始化

*

* @param string $host

* @param string $username

* @param string $password

* @param string $database

* @param string $charset

*/

function __construct($host = &#8216;localhost&#8217;, $username = &#8216;root&#8217;, $password = &#8221;, $database = &#8216;test&#8217;, $charset = &#8216;utf8&#8217;) {

$this->host = $host;

$this->username = $username;

$this->password = $password;

$this->database = $database;

$this->charset = $charset;

set_time_limit(0);//无时间限制

@ob_end_flush();

// 连接数据库

$this->db = @mysql_connect ( $this->host, $this->username, $this->password ) or die( &#8216;

Mysql Connect Error : &#8217;.mysql_error().'

&#8217;);

// 选择使用哪个数据库

mysql_select_db ( $this->database, $this->db ) or die(&#8216;

Mysql Connect Error:&#8217;.mysql_error().'

&#8217;);

// 数据库编码方式

mysql_query ( &#8216;SET NAMES &#8216; . $this->charset, $this->db );

}

/*

* 新增查询数据库表

*/

function getTables() {

$res = my sql _query ( &#8220;SHOW TABLES&#8221; );

$tables = array ();

while ( $row = mysql_fetch_array ( $res ) ) {

$tables [] = $row [0];

}

return $tables;

}

/*

*

* &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;数据库备份start&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-

*/

/**

* 数据库备份

* 参数:备份哪个表(可选),备份目录(可选,默认为backup),分卷大小(可选,默认2000,即2M)

*

* @param $string $dir

* @param int $size

* @param $string $tablename

*/

function backup($tablename = &#8221;, $dir=&#8217;./&#8217;, $size=20480) {

$dir = $dir ? $dir : &#8216;./&#8217;;

// 创建目录

if (! is_dir ( $dir )) {

@mkdir ( $dir, 0777, true ) or die ( &#8216;创建文件夹失败&#8217; );

}

$size = $size ? $size : 1024*20;

$sql = &#8221;;

// 只备份某个表

if (! empty ( $tablename )) {

if(@mysql_num_rows(mysql_query(&#8220;SHOW TABLES LIKE &#8216;&#8221;.$tablename.&#8221;&#8216;&#8221;)) == 1) {

} else {

$this->_show msg (&#8216;表-&#8217; . $tablename .'-不存在,请检查!&#8217;,true);

die();

}

$this->_showMsg(&#8216;正在备份表 &#8217; . $tablename.'&#8217;);

// 插入dump信息

$sql = $this->_retrieve ();

// 插入表结构信息

$sql .= $this->_insert_table_structure ( $tablename );

// 插入数据

$data = mysql_query ( &#8220;select * from &#8221; . $tablename );

// 文件名前面部分

$ file name = date ( &#8216;YmdHis&#8217; ) . &#8220;_&#8221; . $tablename;

// 字段数量

$num_fields = mysql_num_fields ( $data );

// 第几分卷

$p = 1;

// 循环每条记录

while ( $record = mysql_fetch_array ( $data ) ) {

// 单条记录

$sql .= $this->_insert_record ( $tablename, $num_fields, $record );

// 如果大于分卷大小,则写入文件

if (strlen ( $sql ) >= $size * 1024) {

$file = $filename . &#8220;_v&#8221; . $p . &#8220;.sql&#8221;;

if ($this->_write_file ( $sql, $file, $dir )) {

$this->_showMsg(&#8220;表-&#8221; . $tablename . &#8220;-卷-&#8221; . $p . &#8220;-数据备份完成,备份文件 [ &#8221; .$dir . $file .&#8221; ]&#8221;);

} else {

$this->_showMsg(&#8220;备份表 -&#8221; . $tablename . &#8220;- 失败&#8221;,true);

return false;

}

// 下一个分卷

$p ++;

// 重置$sql变量为空,重新计算该变量大小

$sql = &#8220;&#8221;;

}

}

// 及时清除数据

unset($data,$record);

// sql大小不够分卷大小

if ($sql != &#8220;&#8221;) {

$filename .= &#8220;_v&#8221; . $p . &#8220;.sql&#8221;;

if ($this->_write_file ( $sql, $filename, $dir )) {

$this->_showMsg( &#8220;表-&#8221; . $tablename . &#8220;-卷-&#8221; . $p . &#8220;-数据备份完成,备份文件 [ &#8221; .$dir . $filename .&#8221; ]&#8221;);

} else {

$this->_showMsg(&#8220;备份卷-&#8221; . $p . &#8220;-失败
&#8221;);

return false;

}

}

$this->_showMsg(&#8220;恭喜您! 备份成功&#8221;);

} else {

$this->_showMsg(&#8216;正在备份&#8217;);

// 备份全部表

if ($tables = mysql_query ( &#8220;show table status from &#8221; . $this->database )) {

$this->_showMsg(&#8220;读取数据库结构成功!&#8221;);

} else {

$this->_showMsg(&#8220;读取数据库结构失败!&#8221;);

exit ( 0 );

}

// 插入dump信息

$sql .= $this->_retrieve ();

// 文件名前面部分

$filename = date ( &#8216;YmdHis&#8217; ) . &#8220;_all&#8221;;

// 查出所有表

$tables = mysql_query ( &#8216;SHOW TABLES&#8217; );

// 第几分卷

$p = 1;

// 循环所有表

while ( $table = mysql_fetch_array ( $tables ) ) {

// 获取表名

$tablename = $table [0];

// 获取表结构

$sql .= $this->_insert_table_structure ( $tablename );

$data = mysql_query ( &#8220;select * from &#8221; . $tablename );

$num_fields = mysql_num_fields ( $data );

// 循环每条记录

while ( $record = mysql_fetch_array ( $data ) ) {

// 单条记录

$sql .= $this->_insert_record ( $tablename, $num_fields, $record );

// 如果大于分卷大小,则写入文件

if (strlen ( $sql ) >= $size * 1000) {

$file = $filename . &#8220;_v&#8221; . $p . &#8220;.sql&#8221;;

// 写入文件

if ($this->_write_file ( $sql, $file, $dir )) {

$this->_showMsg(&#8220;-卷-&#8221; . $p . &#8220;-数据备份完成,备份文件 [ &#8221;.$dir.$file.&#8221; ]&#8221;);

} else {

$this->_showMsg(&#8220;卷-&#8221; . $p . &#8220;-备份失败!&#8221;,true);

return false;

}

// 下一个分卷

$p ++;

// 重置$sql变量为空,重新计算该变量大小

$sql = &#8220;&#8221;;

}

}

}

// sql大小不够分卷大小

if ($sql != &#8220;&#8221;) {

$filename .= &#8220;_v&#8221; . $p . &#8220;.sql&#8221;;

if ($this->_write_file ( $sql, $filename, $dir )) {

$this->_showMsg(&#8220;-卷-&#8221; . $p . &#8220;-数据备份完成,备份文件 [ &#8221;.$dir.$filename.&#8221; ]&#8221;);

} else {

$this->_showMsg(&#8220;卷-&#8221; . $p . &#8220;-备份失败&#8221;,true);

return false;

}

}

$this->_showMsg(&#8220;恭喜您! 备份成功&#8221;);

}

}

// 及时输出信息

private function _showMsg($msg,$err=false){

$err = $err ? &#8220;ERROR:&#8221; : &#8221; ;

echo &#8220;

&#8221;.$err . $msg.&#8221;

&#8221;;

flush();

}

/**

* 插入数据库备份基础信息

*

* @return string

*/

private function _retrieve() {

$value = &#8221;;

$value .= &#8216;&#8211;&#8216; . $this->ds;

$value .= &#8216;&#8211; MySQL database dump&#8217; . $this->ds;

$value .= &#8216;&#8211; Created by DbManage class, Power By yanue. &#8216; . $this->ds;

$value .= &#8216;&#8211; &#8216; . $this->ds;

$value .= &#8216;&#8211;&#8216; . $this->ds;

$value .= &#8216;&#8211; 主机: &#8216; . $this->host . $this->ds;

$value .= &#8216;&#8211; 生成日期: &#8216; . date ( &#8216;Y&#8217; ) . &#8216; 年 &#8216; . date ( &#8216;m&#8217; ) . &#8216; 月 &#8216; . date ( &#8216;d&#8217; ) . &#8216; 日 &#8216; . date ( &#8216;H:i&#8217; ) . $this->ds;

$value .= &#8216;&#8211; MySQL版本: &#8216; . mysql_get_server_info () . $this->ds;

$value .= &#8216;&#8211; PHP 版本: &#8216; . phpversion () . $this->ds;

$value .= $this->ds;

$value .= &#8216;&#8211;&#8216; . $this->ds;

$value .= &#8216;&#8211; 数据库: `&#8217; . $this->database . &#8216;`&#8217; . $this->ds;

$value .= &#8216;&#8211;&#8216; . $this->ds . $this->ds;

$value .= &#8216;&#8211; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-&#8216;;

$value .= $this->ds . $this->ds;

return $value;

}

/**

* 插入表结构

*

* @param unknown_type $table

* @return string

*/

private function _insert_table_structure($table) {

$sql = &#8221;;

$sql .= &#8220;&#8211;&#8221; . $this->ds;

$sql .= &#8220;&#8211; 表的结构&#8221; . $table . $this->ds;

$sql .= &#8220;&#8211;&#8221; . $this->ds . $this->ds;

// 如果存在则删除表

$sql .= &#8220;DROP TABLE IF EXISTS `&#8221; . $table . &#8216;`&#8217; . $this->sqlEnd . $this->ds;

// 获取详细表信息

$res = mysql_query ( &#8216;SHOW CREATE TABLE `&#8217; . $table . &#8216;`&#8217; );

$row = mysql_fetch_array ( $res );

$sql .= $row [1];

$sql .= $this->sqlEnd . $this->ds;

// 加上

$sql .= $this->ds;

$sql .= &#8220;&#8211;&#8221; . $this->ds;

$sql .= &#8220;&#8211; 转存表中的数据 &#8221; . $table . $this->ds;

$sql .= &#8220;&#8211;&#8221; . $this->ds;

$sql .= $this->ds;

return $sql;

}

/**

* 插入单条记录

*

* @param string $table

* @param int $num_fields

* @param array $record

* @return string

*/

private function _insert_record($table, $num_fields, $record) {

// sql字段逗号分割

$insert = &#8221;;

$comma = &#8220;&#8221;;

$insert .= &#8220;INSERT INTO `&#8221; . $table . &#8220;` VALUES(&#8220;;

// 循环每个子段下面的内容

for($i = 0; $i <$num_fields; $i ++) {

$insert .= ($comma . &#8220;&#8216;&#8221; . mysql_escape_string ( $record [$i] ) . &#8220;&#8216;&#8221;);

$comma = &#8220;,&#8221;;

}

$insert .= &#8220;);&#8221; . $this->ds;

return $insert;

}

/**

* 写入文件

*

* @param string $sql

* @param string $filename

* @param string $dir

* @return boolean

*/

private function _write_file($sql, $filename, $dir) {

$dir = $dir ? $dir : &#8216;./backup/&#8217;;

// 创建目录

if (! is_dir ( $dir )) {

mkdir ( $dir, 0777, true );

}

$re = true;

if (! @$fp = fopen ( $dir . $filename, &#8220;w+&#8221; )) {

$re = false;

$this->_showMsg(&#8220;打开sql文件失败!&#8221;,true);

}

if (! @fwrite ( $fp, $sql )) {

$re = false;

$this->_showMsg(&#8220;写入sql文件失败,请文件是否可写&#8221;,true);

}

if (! @fclose ( $fp )) {

$re = false;

$this->_showMsg(&#8220;关闭sql文件失败!&#8221;,true);

}

return $re;

}

/*

*

* &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-上:数据库导出&#8212;&#8212;&#8212;&#8211;分割线&#8212;&#8212;&#8212;-下:数据库导入&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;

*/

/**

* 导入备份数据

* 说明:分卷文件格式20120516211738_all_v1.sql

* 参数:文件路径(必填)

*

* @param string $sqlfile

*/

function restore($sqlfile) {

// 检测文件是否存在

if (! file_exists ( $sqlfile )) {

$this->_showMsg(&#8220;sql文件不存在!请检查&#8221;,true);

exit ();

}

$this->lock ( $this->database );

// 获取数据库存储位置

$sqlpath = pathinfo ( $sqlfile );

$this->sqldir = $sqlpath [&#8216;dirname&#8217;];

// 检测是否包含分卷,将类似20120516211738_all_v1.sql从_v分开,有则说明有分卷

$ volume = explode ( &#8220;_v&#8221;, $sqlfile );

$volume_path = $volume [0];

$this->_showMsg(&#8220;请勿刷新及关闭浏览器以防止程序被中止,如有不慎!将导致数据库结构受损&#8221;);

$this->_showMsg(&#8220;正在导入备份数据,请稍等!&#8221;);

if (empty ( $volume [1] )) {

$this->_showMsg ( &#8220;正在导入sql:&#8221; . $sqlfile . &#8216;&#8217;);

// 没有分卷

if ($this->_import ( $sqlfile )) {

$this->_showMsg( &#8220;数据库导入成功!&#8221;);

} else {

$this->_showMsg(&#8216;数据库导入失败!&#8217;,true);

exit ();

}

} else {

// 存在分卷,则获取当前是第几分卷,循环执行余下分卷

$volume_id = explode ( &#8220;.sq&#8221;, $volume [1] );

// 当前分卷为$volume_id

$volume_id = intval ( $volume_id [0] );

while ( $volume_id ) {

$tmpfile = $volume_path . &#8220;_v&#8221; . $volume_id . &#8220;.sql&#8221;;

// 存在其他分卷,继续执行

if (file_exists ( $tmpfile )) {

// 执行导入方法

$this->msg .= &#8220;正在导入分卷 $volume_id :&#8221; . $tmpfile . &#8216;
&#8217;;

if ($this->_import ( $tmpfile )) {

} else {

$volume_id = $volume_id ? $volume_id :1;

exit ( &#8220;导入分卷:&#8221; . $tmpfile . &#8216;失败!可能是数据库结构已损坏!请尝试从分卷1开始导入&#8217; );

}

} else {

$this->msg .= &#8220;此分卷备份全部导入成功!
&#8221;;

return;

}

$volume_id ++;

}

}if (empty ( $volume [1] )) {

$this->_showMsg ( &#8220;正在导入sql:&#8221; . $sqlfile . &#8216;&#8217;);

// 没有分卷

if ($this->_import ( $sqlfile )) {

$this->_showMsg( &#8220;数据库导入成功!&#8221;);

} else {

$this->_showMsg(&#8216;数据库导入失败!&#8217;,true);

exit ();

}

} else {

// 存在分卷,则获取当前是第几分卷,循环执行余下分卷

$volume_id = explode ( &#8220;.sq&#8221;, $volume [1] );

// 当前分卷为$volume_id

$volume_id = intval ( $volume_id [0] );

while ( $volume_id ) {

$tmpfile = $volume_path . &#8220;_v&#8221; . $volume_id . &#8220;.sql&#8221;;

// 存在其他分卷,继续执行

if (file_exists ( $tmpfile )) {

// 执行导入方法

$this->msg .= &#8220;正在导入分卷 $volume_id :&#8221; . $tmpfile . &#8216;
&#8217;;

if ($this->_import ( $tmpfile )) {

} else {

$volume_id = $volume_id ? $volume_id :1;

exit ( &#8220;导入分卷:&#8221; . $tmpfile . &#8216;失败!可能是数据库结构已损坏!请尝试从分卷1开始导入&#8217; );

}

} else {

$this->msg .= &#8220;此分卷备份全部导入成功!
&#8221;;

return;

}

$volume_id ++;

}

}

}

/**

* 将sql导入到数据库(普通导入)

*

* @param string $sqlfile

* @return boolean

*/

private function _import($sqlfile) {

// sql文件包含的sql语句数组

$sqls = array ();

$f = fopen ( $sqlfile, &#8220;rb&#8221; );

// 创建表缓冲变量

$create_table = &#8221;;

while ( ! feof ( $f ) ) {

// 读取每一行sql

$line = fgets ( $f );

// 这一步为了将创建表合成完整的sql语句

// 如果结尾没有包含&#8217;;'(即为一个完整的sql语句,这里是插入语句),并且不包含&#8217;ENGINE='(即创建表的最后一句)

if (! preg_match ( &#8216;/;/&#8217;, $line ) || preg_match ( &#8216;/ENGINE=/&#8217;, $line )) {

// 将本次sql语句与创建表sql连接存起来

$create_table .= $line;

// 如果包含了创建表的最后一句

if (preg_match ( &#8216;/ENGINE=/&#8217;, $create_table)) {

//执行sql语句创建表

$this->_insert_into($create_table);

// 清空当前,准备下一个表的创建

$create_table = &#8221;;

}

// 跳过本次

continue;

}

//执行sql语句

$this->_insert_into($line);

}

fclose ( $f );

return true;

}

//插入单条sql语句

private function _insert_into($sql){

if (! mysql_query ( trim ( $sql ) )) {

$this->msg .= mysql_error ();

return false;

}

}

/*

* &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-数据库导入end&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;

*/

// 关闭数据库连接

private function close() {

mysql_close ( $this->db );

}

// 锁定数据库,以免备份或导入时出错

private function lock($tablename, $op = &#8220;WRITE&#8221;) {

if (mysql_query ( &#8220;lock tables &#8221; . $tablename . &#8221; &#8221; . $op ))

return true;

else

return false;

}

// 解锁

private function unlock() {

if (mysql_query ( &#8220;unlock tables&#8221; ))

return true;

else

return false;

}

// 析构

function __destruct() {

if($this->db){

mysql_query ( &#8220;unlock tables&#8221;, $this->db );

mysql_close ( $this->db );

}

}

}

$db = new DbManage(&#8220;localhost&#8221;,&#8221;root&#8221;,&#8221;root&#8221;,&#8221;dbname&#8221;);

$db->backup(&#8220;&#8221;,&#8221;&#8221;,&#8221;&#8221;);

?>


推荐阅读
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • CentOS 6.5安装VMware Tools及共享文件夹显示问题解决方法
    本文介绍了在CentOS 6.5上安装VMware Tools及解决共享文件夹显示问题的方法。包括清空CD/DVD使用的ISO镜像文件、创建挂载目录、改变光驱设备的读写权限等步骤。最后给出了拷贝解压VMware Tools的操作。 ... [详细]
  • r2dbc配置多数据源
    R2dbc配置多数据源问题根据官网配置r2dbc连接mysql多数据源所遇到的问题pom配置可以参考官网,不过我这样配置会报错我并没有这样配置将以下内容添加到pom.xml文件d ... [详细]
  • WhenIusepythontoapplythepymysqlmoduletoaddafieldtoatableinthemysqldatabase,itdo ... [详细]
  • PDO MySQL
    PDOMySQL如果文章有成千上万篇,该怎样保存?数据保存有多种方式,比如单机文件、单机数据库(SQLite)、网络数据库(MySQL、MariaDB)等等。根据项目来选择,做We ... [详细]
  • 本文介绍了使用Python解析C语言结构体的方法,包括定义基本类型和结构体类型的字典,并提供了一个示例代码,展示了如何解析C语言结构体。 ... [详细]
  • 本文主要复习了数据库的一些知识点,包括环境变量设置、表之间的引用关系等。同时介绍了一些常用的数据库命令及其使用方法,如创建数据库、查看已存在的数据库、切换数据库、创建表等操作。通过本文的学习,可以加深对数据库的理解和应用能力。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
author-avatar
陈小超Sum
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有