本文目录导读:

- 方案一:使用
mysqldump命令行工具(最推荐,性能最好) - 方案二:纯 PHP 逐表导出(无服务器依赖)
- 方案三:使用现成的 PHP 库(如
Ifsnop/mysqldump-php) - 方案四:定时自动备份(Cron / 任务计划)
- 安全与最佳实践
- 总结选择建议
在 PHP 项目中实现数据备份,核心思路是通过 PHP 代码调用数据库导出工具(如 mysqldump)或使用 PHP 自身的数据库函数逐表导出。
以下是几种常见的实现方案,从简单到灵活,你可以根据项目规模和权限选择:
使用 mysqldump 命令行工具(最推荐,性能最好)
这是最标准、最高效的方法。mysqldump 会生成完整的 SQL 文件,包括表结构和数据。
前提条件:
- 服务器上安装了 MySQL 客户端(
mysqldump命令)。 - PHP 的
exec()、shell_exec()、system()等函数未被禁用。
PHP 代码示例:
<?php
// 数据库配置
$db_host = 'localhost';
$db_user = 'root';
$db_pass = 'your_password';
$db_name = 'your_database';
// 备份文件保存路径
$backup_dir = __DIR__ . '/backups/';
if (!is_dir($backup_dir)) {
mkdir($backup_dir, 0777, true);
}
$backup_file = $backup_dir . $db_name . '_' . date('Y-m-d_H-i-s') . '.sql';
// 构建 mysqldump 命令
$command = sprintf(
'mysqldump --host=%s --user=%s --password=%s --databases %s --routines --events --result-file=%s 2>&1',
escapeshellarg($db_host),
escapeshellarg($db_user),
escapeshellarg($db_pass),
escapeshellarg($db_name),
escapeshellarg($backup_file)
);
// 执行命令
$output = null;
$return_var = null;
exec($command, $output, $return_var);
if ($return_var === 0) {
echo "备份成功!文件:{$backup_file}";
// 可以记录日志或发送通知
} else {
echo "备份失败:<br>" . implode("\n", $output);
}
?>
安全与路径注意事项:
- 如果在 Windows 下开发,需将
mysqldump.exe的全路径写入命令,C:\xampp\mysql\bin\mysqldump.exe。 - 密码可能暴露在
ps aux命令下(不安全),更推荐使用~/.my.cnf配置文件([client]段)来代替--password=参数。
纯 PHP 逐表导出(无服务器依赖)
如果服务器禁用了 exec() 或没有安装 mysqldump,可以使用 PHP 的 PDO 或 mysqli 自行读取数据并拼装 SQL。
优点: 不依赖外部命令。 缺点: 对大数据库很慢,内存占用高,处理 BLOB 类型数据较麻烦。
代码思路与核心片段:
<?php
// 数据库连接
$pdo = new PDO("mysql:host=$db_host;dbname=$db_name;charset=utf8mb4", $db_user, $db_pass);
$pdo->setAttribute(PDO::ATTR_ORIGIN, PDO::FETCH_ASSOC);
$backup_sql = "-- 数据库备份文件 ({$db_name})\n-- 生成时间:".date('Y-m-d H:i:s')."\n\n";
// 1. 获取所有表
$tables = $pdo->query("SHOW TABLES")->fetchAll(PDO::FETCH_COLUMN);
foreach ($tables as $table) {
// 2. 获取建表语句
$create = $pdo->query("SHOW CREATE TABLE `$table`")->fetch();
$backup_sql .= "DROP TABLE IF EXISTS `$table`;\n";
$backup_sql .= $create['Create Table'] . ";\n\n";
// 3. 获取所有数据,并生成 INSERT 语句
// 注意:对于大表,最好分页处理(LIMIT/OFFSET),避免内存溢出
$rows = $pdo->query("SELECT * FROM `$table`")->fetchAll();
foreach ($rows as $row) {
$escaped_values = array_map(function($value) use ($pdo) {
return $pdo->quote($value); // 自动转义并加引号
}, $row);
$backup_sql .= "INSERT INTO `$table` VALUES (" . implode(',', $escaped_values) . ");\n";
}
$backup_sql .= "\n";
}
// 4. 写入文件
file_put_contents($backup_dir . '/backup_' . date('Y-m-d_H-i-s') . '.sql', $backup_sql);
echo "备份成功!";
?>
注意: 如果表很大且数据量超过百万,这种方式会由于一次性加载全部数据而导致内存耗尽,改进方案是使用
foreach($stmt->fetch(PDO::FETCH_ASSOC)循环写入文件,而不是先全部fetchAll()。
使用现成的 PHP 库(如 Ifsnop/mysqldump-php)
如果不想自己处理 SQL 占位符、BLOB 等问题,可以使用 Composer 第三方库:ifsnop/mysqldump-php,它用纯 PHP 实现了 mysqldump 的功能,不需要 exec()。
安装:
composer require ifsnop/mysqldump-php
使用示例:
<?php
use Ifsnop\Mysqldump as IMysqldump;
require_once 'vendor/autoload.php';
$dump = new IMysqldump\Mysqldump(
"mysql:host=localhost;dbname=your_db",
"root",
"password",
[
'compress' => IMysqldump\Mysqldump::GZIP, // 启用压缩
'single-transaction' => true,
'routines' => true,
]
);
$dump->start('backup.sql.gz'); // 直接生成 .sql.gz 压缩文件
echo "备份成功!";
优点: 兼容性好、支持压缩、自动处理大数据(流式写入)、无需 exec()。
定时自动备份(Cron / 任务计划)
手动执行备份不靠谱,通常需要设置定时任务,步骤如下:
写一个 PHP 脚本(backup.php),独立运行。
在 Linux / Mac 上设置 crontab:
crontab -e # 每天凌晨 3 点执行备份(使用 PHP CLI 模式运行脚本) 0 3 * * * /usr/bin/php /path/to/your/backup.php >> /var/log/backup.log 2>&1
在 Windows 上:
使用系统“任务计划程序”,设置触发器,执行 php.exe 路径 + backup.php 路径。
保留策略(重要): 在备份脚本中加入过期删除逻辑,防止磁盘爆满:
// 只保留最近 30 天的备份
$files = glob($backup_dir . '*.sql*');
usort($files, function($a, $b) {
return filemtime($a) - filemtime($b);
});
while (count($files) > 30) {
$file_to_delete = array_shift($files);
unlink($file_to_delete);
}
安全与最佳实践
- 数据库密码不要硬编码在脚本中:使用
.env文件 +vlucas/phpdotenv库,或单独存放配置且将该文件设置为644权限且不允许 Web 访问。 - 备份文件不要放在 Web 可访问目录内:放在
backups/目录同时设置.htaccess禁止访问(Deny from all)。 - 压缩备份:对于大数据库,推荐使用 Gzip 压缩(
.sql.gz),体积可减少 60%~80%。 - 远程备份:在备份成功后,使用
scp、FTP(PHP FTP 函数)或云存储 SDK(如 AWS S3、OSS)将备份文件传送到异地服务器,防止服务器硬盘损坏导致数据丢失。
总结选择建议
| 场景 | 推荐方案 |
|---|---|
| 生产环境、性能要求高 | 方案一(mysqldump + cron) |
| 虚拟主机禁用了 exec() | 方案三(ifsnop/mysqldump-php) |
| 小型项目、SQLite 数据库 | 方案二(纯 PHP 逐表导出) |
| 需要异地备份 + 压缩 | 方案三 + 上传到 S3/OSS |
最稳定、最推荐的组合: mysqldump(方案一)或 ifsnop/mysqldump-php(方案三) + cron 定时 + 压缩 + 异地存储。