PHP实现MySQL数据库备份与还原(基于mysql扩展)
本文将演示如何利用PHP原生的 mysql 扩展编写一个简易的数据库备份还原类。通过读取表结构生成建表语句,遍历数据表生成插入语句,并结合特殊注释分割SQL文件,最终实现完整的备份与恢复流程。
环境准备:连接数据库与初始化类属性
首先定义一个 dbBackup 类,用于存储连接的默认参数。需要设置主机地址、用户名、密码、目标数据库名以及字符集(推荐 utf8)。
class dbBackup {
public $host = 'localhost'; // 数据库地址
public $user = 'root'; // 登录名
public $pwd = ''; // 密码
public $database; // 数据库名
public $charset = 'utf8'; // 数据库连接编码
}
接着编写内部连接方法 db(),建立连接后设置当前使用的数据库和字符集编码。
function db() {
$con = mysql_connect($this->host, $this->user, $this->pwd);
if (!$con) die('Could not connect');
$db_selected = mysql_select_db($this->database, $con);
if (!$db_selected) die("Can't use select db");
mysql_set_charset($this->charset); // 设置编码
return $con;
}
获取数据表集合与结构
备份的第一步是列出所有表名,随后逐个提取它们的建表语句(CREATE TABLE)。
第1步:查询数据库表集合
目的:获取当前库下所有数据表的名字列表。
- 入口函数:
tblist() - 动作:执行
SHOW TABLES FROM {$this->database}并遍历结果集。
function tblist() {
$list = array();
$rs = mysql_query("SHOW TABLES FROM $this->database");
while ($temp = mysql_fetch_row($rs)) {
$list[] = $temp[0];
}
return $list;
}
第2步:生成建表SQL
目的:获取每张表的完整 CREATE TABLE SQL语句,用于后续还原。
- 入口函数:
sqlcreate() - 关键参数:使用固定的注释标记(如
-- <xjx> --)作为每条完整SQL的分隔符,方便解析时拆分。
function sqlcreate() {
$sql = '';
$tb = $this->tblist();
foreach ($tb as $v) {
$rs = mysql_query("SHOW CREATE TABLE $v");
$temp = mysql_fetch_row($rs);
$sql .= "-- 表的结构:{$temp[0]} --\r\n";
$sql .= "{$temp[1]};-- <xjx> --\r\n\r\n";
}
return $sql;
}
注意:每句完整的SQL后必须加上分号 (;) 才能被MYSQL正确识别为一条语句。
生成数据插入语句(INSERT INTO)
这是备份的核心步骤。需要遍历所有表的数据,逐行提取并格式化为 INSERT 语句。在处理过程中,必须对特殊值和字符串进行转义。
第3步:构建INSERT SQL字符串
目的:将数据转化为可执行的 INSERT INTO ... VALUES 语句。
- 入口函数:
sqlinsert() - 重要参数:利用
mysql_real_escape_string处理字符串防止注入或语法错误;正确处理NULL值(不加引号)。 - 完成状态:返回拼接好的包含所有
INSERT语句的大段SQL文本。
function sqlinsert() {
$sql = '';
$tb = $this->tblist();
foreach ($tb as $v) {
$rs = mysql_query("SELECT * FROM $v");
if (!mysql_num_rows($rs)) continue; // 空表跳过
$sql .= "-- 表的数据:$v --\r\n";
$sql .= "INSERT INTO `$v` VALUES\r\n";
while ($temp = mysql_fetch_row($rs)) {
$sql .= '(';
foreach ($temp as $v2) {
if ($v2 === null) {
$sql .= 'NULL,';
} else {
$v2 = mysql_real_escape_string($v2);
$sql .= "'$v2',";
}
}
// 去除行末尾多余的逗号
$sql = mb_substr($sql, 0, -1);
$sql .= '),\r\n';
}
// 去除最后一条记录的多余逗号和新行
$sql = mb_substr($sql, 0, -3);
// 添加结束标记供还原时切分
$sql .= ';-- <xjx> --\r\n\r\n';
}
return $sql;
}
执行备份操作
将上述两步生成的SQL合并,并写入到指定的本地文件中即可完成备份。
第4步:调用写文件接口
- 入口函数:
beifen($filename) - 参数:需要保存的文件路径(如
'backup.sql')。
function beifen($filename) {
$this->db(); // 确保连接
$data = $this->sqlcreate() . $this->sqlinsert();
return file_put_contents($filename, $data);
}
执行还原操作
还原的逻辑是先清空旧数据(或删除原表),再按顺序解析备份文件中的SQL并逐一执行。
风险提醒:以下操作会删除(Drop)现有表!请确保已确认备份文件有效性或在测试环境运行。
第5步:解析并执行还原脚本
- 入口函数:
huanyuan($filename) - 参数:备份文件的本地路径。
- 关键逻辑:使用与备份时相同的分隔符(
-- <xjx> --)对文件内容进行explode切割,分离出独立的SQL语句。
function huanyuan($filename) {
$this->db();
// 1. 删除现有表
$list = $this->tblist();
$tb = implode(',`', $list);
$tb = '`' . $tb . '`';
if ($tb && strpos($tb, ',') !== false) {
mysql_query("DROP TABLE $tb");
}
// 2. 读取并分割SQL文件
$str = file_get_contents($filename);
$arr = explode('-- <xjx> --', $str);
array_pop($arr); // 移除最后一个空元素
// 3. 依次执行SQL
foreach ($arr as $v) {
v = trim($v);
if (!empty(v)) {
$rs = mysql_query($v);
if (!$rs) return false;
}
}
return true;
}
使用示例与完整代码参考
实例化类并调用对应方法即可运行。
// 配置参数
$x = new dbBackup();
$x->database = 'test_db';
// 执行备份
$rs = $x->beifen('db_backup.sql');
var_dump($rs);
// 执行还原
$rs = $x->huanyuan('db_backup.sql');
var_dump($rs);
总结与注意事项
本方案利用了 mysql 扩展的特性实现了轻量级的库级备份。但在实际生产环境中需要注意以下几点:
- API弃用:
mysql_*系列函数已在 PHP 7.0+ 中被移除,建议使用mysqli或PDO改写底层连接逻辑。 - 性能瓶颈:该方法将所有SQL拉取到内存中拼接成一个大字符串,不适合千万级以上的巨型数据库,容易引发内存溢出。
- 安全性:建议在实际项目中增加文件写入权限检查和SQL执行后的错误日志记录功能。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









