如何仅用PHP备份MariaDB单个数据集?删除前备份待删数据的最优方案
嘿,我来帮你搞定这两个PHP+MariaDB的问题,都是日常开发里很实用的场景:
一、仅用PHP备份MariaDB单个数据集
这里分两种常见场景,你可以根据需求选择:
1. 备份单个完整数据表
如果要备份某张表的全部数据(结构+内容),用PHP结合PDO导出SQL是最稳妥的方式,恢复时直接执行SQL就能还原。给你写个完整的可复用示例:
<?php // 数据库连接信息 $dsn = 'mysql:host=localhost;dbname=your_database;charset=utf8mb4'; $username = 'your_username'; $password = 'your_password'; try { $pdo = new PDO($dsn, $username, $password); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $targetTable = 'your_target_table'; $backupFilename = "{$targetTable}-backup-" . date('Y-m-d-His') . '.sql'; // 先导出表结构(恢复时需要重建表) $createStmt = $pdo->query("SHOW CREATE TABLE `{$targetTable}`"); $createSql = $createStmt->fetch(PDO::FETCH_ASSOC)['Create Table'] . ";\n\n"; // 导出表数据为INSERT语句 $dataStmt = $pdo->query("SELECT * FROM `{$targetTable}`"); $allRows = $dataStmt->fetchAll(PDO::FETCH_ASSOC); $insertSql = ''; if (!empty($allRows)) { $columns = implode('`, `', array_keys($allRows[0])); $insertSql .= "INSERT INTO `{$targetTable}` (`{$columns}`) VALUES\n"; $valueRows = []; foreach ($allRows as $row) { // 用PDO的quote方法自动转义,避免SQL注入 $escapedVals = array_map(fn($val) => $pdo->quote($val), $row); $valueRows[] = '(' . implode(', ', $escapedVals) . ')'; } $insertSql .= implode(",\n", $valueRows) . ";"; } // 写入备份文件 file_put_contents($backupFilename, $createSql . $insertSql); echo "备份完成,文件:{$backupFilename}"; } catch (PDOException $e) { die("备份失败:" . $e->getMessage()); } ?>
2. 备份即将删除的特定数据集
如果只是要备份清理脚本里要删除的那批记录,不用导出整个表,先查询目标数据备份,再执行删除:
<?php // 数据库连接部分同上... // 你的删除条件,比如过期的记录 $deleteCondition = "expire_time < NOW()"; // 第一步:查询要删除的数据并备份 $selectStmt = $pdo->prepare("SELECT * FROM `your_target_table` WHERE {$deleteCondition}"); $selectStmt->execute(); $rowsToBackup = $selectStmt->fetchAll(PDO::FETCH_ASSOC); // 先选JSON格式备份,后面会说为什么比序列化好 $backupJson = json_encode($rowsToBackup, JSON_PRETTY_PRINT); file_put_contents("deleted-records-backup-" . date('Y-m-d-His') . '.json', $backupJson); // 第二步:执行删除 $deleteStmt = $pdo->prepare("DELETE FROM `your_target_table` WHERE {$deleteCondition}"); $deleteStmt->execute(); echo "已备份" . count($rowsToBackup) . "条记录并完成删除!"; ?>
二、替代序列化写入的更优方案
你说的序列化方案确实能工作,但有几个硬伤:序列化内容完全不可读,没法手动检查数据;而且PHP版本更新可能导致序列化格式不兼容,跨版本恢复容易出问题。给你推荐几个更实用的方案:
1. JSON格式(首推)
优点太多了:人类可读,用普通文本编辑器就能查看内容;跨语言兼容,就算以后用其他语言恢复也没问题;PHP的json_encode/json_decode处理起来超级方便。恢复时的代码示例:
<?php // 连接数据库同上... $backupData = json_decode(file_get_contents('deleted-records-backup-xxxxxx.json'), true); foreach ($backupData as $row) { $columns = implode('`, `', array_keys($row)); $placeholders = ':' . implode(', :', array_keys($row)); $insertStmt = $pdo->prepare("INSERT INTO `your_target_table` (`{$columns}`) VALUES ({$placeholders})"); $insertStmt->execute($row); } echo "恢复完成!"; ?>
2. CSV格式(适合大数据量)
如果要备份的记录特别多,CSV文件体积比JSON小,而且可以直接用Excel、Numbers打开查看,适合需要做数据核对的场景:
// 备份时 $fp = fopen('deleted-records-backup-' . date('Y-m-d-His') . '.csv', 'w'); // 先写入表头(字段名) fputcsv($fp, array_keys($rowsToBackup[0])); // 逐行写入数据 foreach ($rowsToBackup as $row) { fputcsv($fp, $row); } fclose($fp); // 恢复时 $fp = fopen('deleted-records-backup-xxxxxx.csv', 'r'); $headers = fgetcsv($fp); // 读取表头 while ($rowData = fgetcsv($fp)) { $row = array_combine($headers, $rowData); // 插入数据库的代码和JSON恢复时一致 $columns = implode('`, `', $headers); $placeholders = ':' . implode(', :', $headers); $insertStmt = $pdo->prepare("INSERT INTO `your_target_table` (`{$columns}`) VALUES ({$placeholders})"); $insertStmt->execute($row); } fclose($fp);
3. SQL INSERT语句
如果备份的目的就是为了以后快速恢复到数据库,直接导出成INSERT语句最方便,恢复时不用写PHP代码,直接把SQL文件导入MariaDB就行(比如用phpMyAdmin或者mysql命令行)。具体代码参考第一个场景里生成INSERT语句的部分。
4. 调用mysqldump(高效但需权限)
如果你的服务器允许PHP执行系统命令,用mysqldump备份单个表效率更高,尤其是数据量极大的时候。注意一定要做好参数过滤,防止命令注入:
<?php $dbName = 'your_database'; $tableName = 'your_target_table'; $backupFile = "{$tableName}-backup-" . date('Y-m-d-His') . '.sql'; // 用escapeshellarg处理参数,避免命令注入 $command = sprintf( "mysqldump -u %s -p%s %s %s > %s", escapeshellarg('your_username'), escapeshellarg('your_password'), escapeshellarg($dbName), escapeshellarg($tableName), escapeshellarg($backupFile) ); exec($command, $output, $returnCode); if ($returnCode === 0) { echo "备份成功:{$backupFile}"; } else { echo "备份失败,错误信息:" . implode("\n", $output); } ?>
总结一下
- 备份单个数据集:整表备份优先选SQL导出或mysqldump;特定记录备份用JSON或CSV更灵活。
- 替代序列化:首推JSON(兼顾易用性和可读性),大数据量选CSV,要直接恢复选SQL。
内容的提问来源于stack exchange,提问作者Steven
相关产品推荐
相关产品推荐

