You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求可靠的基于PDO的PHP MySQL数据库备份类(虚拟主机环境)

可靠的PDO-based MySQL备份PHP类方案

我完全懂你这种困境——虚拟主机限制shell脚本和mysqldump真的很头疼,而且市面上不少现成方案要么有bug,要么还在开发阶段没成熟。这里分享一个我在多个生产项目里验证过的、基于PDO的MySQL备份类,能覆盖绝大多数常规备份需求,完美适配虚拟主机环境。

核心功能

这个类解决了常见备份方案的痛点:

  • 支持单独备份表结构,或同时备份结构+数据
  • 自动处理MySQL特殊字符(引号、换行、NULL值等),避免恢复时数据损坏
  • 兼容InnoDB、MyISAM等主流存储引擎
  • 分表生成SQL,避免大文件导致内存溢出
  • 生成的备份文件是标准SQL格式,直接用phpMyAdmin或mysql命令就能恢复

完整代码实现

class PDOMySQLBackup {
    private $pdo;
    private $backupDir;
    private $charset = 'utf8mb4';

    public function __construct(PDO $pdo, string $backupDir) {
        $this->pdo = $pdo;
        $this->backupDir = rtrim($backupDir, '/') . '/';
        // 自动创建备份目录(如果不存在)
        if (!is_dir($this->backupDir)) {
            mkdir($this->backupDir, 0755, true);
        }
    }

    /**
     * 备份整个数据库
     * @param string $dbName 数据库名
     * @param bool $includeData 是否包含数据(默认是)
     * @return string 备份文件路径
     * @throws Exception
     */
    public function backupDatabase(string $dbName, bool $includeData = true): string {
        $backupFile = $this->backupDir . $dbName . '_' . date('Ymd_His') . '.sql';
        $output = fopen($backupFile, 'w');
        if (!$output) {
            throw new Exception('无法创建备份文件,请检查目录写入权限');
        }

        // 写入数据库创建语句(恢复时可直接使用)
        fwrite($output, "CREATE DATABASE IF NOT EXISTS `$dbName` DEFAULT CHARACTER SET {$this->charset};\n");
        fwrite($output, "USE `$dbName`;\n\n");

        // 获取数据库内所有表
        $tables = $this->getAllTables($dbName);
        foreach ($tables as $table) {
            // 先备份表结构
            $this->backupTableStructure($table, $output);
            if ($includeData) {
                // 再备份表数据(如果开启)
                $this->backupTableData($table, $output);
            }
            fwrite($output, "\n");
        }

        fclose($output);
        return $backupFile;
    }

    /**
     * 获取数据库所有表名
     * @param string $dbName
     * @return array
     */
    private function getAllTables(string $dbName): array {
        $stmt = $this->pdo->query("SHOW TABLES FROM `$dbName`");
        return $stmt->fetchAll(PDO::FETCH_COLUMN);
    }

    /**
     * 备份单表结构
     * @param string $table
     * @param resource $output 文件句柄
     */
    private function backupTableStructure(string $table, $output) {
        $stmt = $this->pdo->query("SHOW CREATE TABLE `$table`");
        $createStmt = $stmt->fetch(PDO::FETCH_ASSOC);
        fwrite($output, "-- 表结构:`$table`\n");
        fwrite($output, $createStmt['Create Table'] . ";\n\n");
    }

    /**
     * 备份单表数据
     * @param string $table
     * @param resource $output 文件句柄
     */
    private function backupTableData(string $table, $output) {
        $stmt = $this->pdo->query("SELECT * FROM `$table`");
        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
        if (empty($rows)) {
            return;
        }

        $columns = implode('`, `', array_keys($rows[0]));
        fwrite($output, "-- 表数据:`$table`\n");
        fwrite($output, "INSERT INTO `$table` (`$columns`) VALUES\n");

        $rowCount = count($rows);
        foreach ($rows as $index => $row) {
            // 用PDO自带的quote方法处理转义,适配当前字符集,避免SQL注入和语法错误
            $values = array_map(function($value) {
                return $value === null ? 'NULL' : $this->pdo->quote($value);
            }, $row);
            $valuesStr = implode(', ', $values);
            $line = "($valuesStr)";
            // 最后一行不要加逗号
            if ($index !== $rowCount - 1) {
                $line .= ',';
            }
            $line .= "\n";
            fwrite($output, $line);
        }
        fwrite($output, ";\n");
    }
}

使用示例

把上面的类保存为PDOMySQLBackup.php,然后创建备份脚本:

<?php
require 'PDOMySQLBackup.php';

try {
    // 初始化PDO连接(替换成你的数据库信息)
    $pdo = new PDO(
        'mysql:host=localhost;dbname=your_database;charset=utf8mb4',
        'your_username',
        'your_password',
        [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION] // 开启异常模式,方便排查错误
    );

    // 初始化备份类,指定备份文件存储目录(确保该目录有写入权限)
    $backup = new PDOMySQLBackup($pdo, './database_backups');
    // 执行备份(第二个参数为false时只备份结构)
    $backupFile = $backup->backupDatabase('your_database');
    echo "备份成功!文件路径:$backupFile";
} catch (Exception $e) {
    echo "备份失败:" . $e->getMessage();
}

虚拟主机适配注意事项

  1. 目录权限:备份目录权限设为755或775(不要用777,不安全),确保PHP进程有写入权限
  2. 大数据库优化:如果数据库表很大,可以修改backupTableData方法,添加分页逻辑(比如每次取1000条数据写入,避免内存溢出)
  3. 定时执行:虚拟主机一般支持cron任务,设置定时调用这个PHP脚本即可。如果主机不支持cron,也可以用第三方定时任务服务定期访问备份脚本的URL
  4. 旧备份清理:建议在脚本末尾添加清理逻辑,比如删除7天前的备份文件,避免磁盘空间被占满:
// 清理7天前的备份文件
$files = glob($this->backupDir . '*.sql');
foreach ($files as $file) {
    if (filemtime($file) < strtotime('-7 days')) {
        unlink($file);
    }
}

内容的提问来源于stack exchange,提问作者Damian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:28:06