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

这篇文章主要介绍了php实现MySQL数据库备份与还原类,可实现针对MySQL数据库的导入与导出功能,并且包含了针对数据库操作时的加锁与解锁等功能,非常具有实用价值,需要的朋友可以参考下

本文实例讲述了php实现MySQL数据库备份与还原类。分享给大家供大家参考。具体分析如下:

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

希望本文所述对大家的PHP程序设计有所帮助。