PHP - PDO mysql 备份到远程主机?

发布于 2024-09-25 02:27:54 字数 83 浏览 4 评论 0原文

欢迎,

我如何使用 PHP PDO 创建数据库(内部所有表)到远程 mysql 服务器的完整备份?

有什么简单的方法吗?

Welcome,

How can i create a full backup of my database (all tables inside) to remote mysql server using PHP PDO ?

Is there any easy way ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

战皆罪 2024-10-02 02:27:54

我将从有关复制的 MySQL 文档开始。我不建议使用 PHP 和 PDO 执行此操作。当您使用正确的工具来完成工作时,您将获得更好的结果。恕我直言。

I would start with the MySQL documentation on replication. I would not recommend doing this with PHP and PDO. You'll have better results when you use the right tool for the job. IMHO.

北斗星光 2024-10-02 02:27:54

您必须对源数据库中的每个表执行 SELECT * FROM [table],然后在目标数据库上运行一个大事务,删除所有先前的表数据,然后插入新的表数据数据。
基本上类似于此代码片段:

<?php
// $srcDB and $destDB are instances of PDO.
// $tableNames is an array of tables in the correct order.
//
//   $srcDB = new PDO(...);
//   $destDB = new PDO(...);
//   $tableNames = array('table1', 'table2');

$srcDB->beginTransaction();
$destDB->beginTransaction();

try {
    foreach ($tableNames as $tableName) {
        // Fetch records from source
        $srcStatement = $srcDB->query('SELECT * FROM '.$tableName);
        $rows = $srcStatement->fetchAll(PDO::FETCH_NUM);
        // Free resources allocated by query
        $srcStatement->closeCursor();
        $srcStatement = null;

        if ( count($rows) === 0 )
            continue; // No rows

        // Prepare records to insert
        $insertValues = array();
        foreach ($rows as $row)
            $insertValues[] = '('.implode(',', array_map(array($destDB, 'quote'), $row)).')';

        // Clear destination table      
        if ( $destDB->exec('DELETE FROM '.$tableName) === false )
            throw new Exception('DELETE failed for table '.$tableName);

        // Write records
        if ( $destDB->exec('INSERT INTO '.$tableName.' VALUES '.implode(',', $insertValues)) === false )
            throw new Exception('INSERT failed for table '.$tableName);
    }

} catch (Exception $e) {
    $srcDB->rollBack();
    $destDB->rollBack();
    throw $e;
}

$result = $destDB->commit();
$srcDB->rollBack(); // or $srcDB->commit() - we did not change the source DB though

if ( !$result )
    throw new Exception('Commit failed');

// Success
?>

注意:

  • 至少对于 MySQL,引用 INT(例如主键 ID)不会导致错误并且可以正常工作,因此 中的 $destDB->quote() array_map() 应该是安全的,但我不确定这是否适用于所有数据类型和所有数据库系统。
  • 在单个事务中完成所有操作可以防止不一致的备份。
  • 该示例假设两个数据库具有相同的数据库结构,所有列都以完全相同的顺序出现。
  • 必须按照正确的顺序删除和构建表,以免违反任何外键约束,否则备份可能会失败。
  • 广泛测试(最好是在带有实时数据副本的专用测试系统上)使用不同的场景(部分或所有表为空、表有很多行、所有表非空等),以确保它工作可靠,并且您的备份脚本不会由于 内存限制设置)。通过使用 mysqldump 等转储目标数据库与源数据库进行比较,以验证它们是否相同以及备份是否完整。在最坏的情况下,您甚至可能会遇到讨厌的 PDO 错误,您可能需要解决这些错误 - Google 和 SO 是您的朋友:-)。

编辑:
另外还可以使用特殊的 INFORMATION_SCHEMA 数据库 来查询表名并自动确定外键依赖关系。
另外,您可能需要禁用外键检查<当您具有自引用外键关系时,在传输过程中在目标数据库上执行 /a>(并在之后重新启用它们),以防止由于违反约束而导致失败。

You'll have to perform a SELECT * FROM [table] on every table you have in your source database, then run a big transaction on your destination database that deletes all previous table data and then inserts the new data.
Basically something similar to this snippet:

<?php
// $srcDB and $destDB are instances of PDO.
// $tableNames is an array of tables in the correct order.
//
//   $srcDB = new PDO(...);
//   $destDB = new PDO(...);
//   $tableNames = array('table1', 'table2');

$srcDB->beginTransaction();
$destDB->beginTransaction();

try {
    foreach ($tableNames as $tableName) {
        // Fetch records from source
        $srcStatement = $srcDB->query('SELECT * FROM '.$tableName);
        $rows = $srcStatement->fetchAll(PDO::FETCH_NUM);
        // Free resources allocated by query
        $srcStatement->closeCursor();
        $srcStatement = null;

        if ( count($rows) === 0 )
            continue; // No rows

        // Prepare records to insert
        $insertValues = array();
        foreach ($rows as $row)
            $insertValues[] = '('.implode(',', array_map(array($destDB, 'quote'), $row)).')';

        // Clear destination table      
        if ( $destDB->exec('DELETE FROM '.$tableName) === false )
            throw new Exception('DELETE failed for table '.$tableName);

        // Write records
        if ( $destDB->exec('INSERT INTO '.$tableName.' VALUES '.implode(',', $insertValues)) === false )
            throw new Exception('INSERT failed for table '.$tableName);
    }

} catch (Exception $e) {
    $srcDB->rollBack();
    $destDB->rollBack();
    throw $e;
}

$result = $destDB->commit();
$srcDB->rollBack(); // or $srcDB->commit() - we did not change the source DB though

if ( !$result )
    throw new Exception('Commit failed');

// Success
?>

Notes:

  • At least for MySQL, quoting INTs (e.g. primary key IDs) causes no errors and works properly, so $destDB->quote() in the array_map() should be safe then, but I don't know for sure if this applies for all data types and all database systems.
  • Doing everything in a single transaction prevents inconsistent backups.
  • The example assumes that you have the same database structure in both databases, with all columns appearing in exactly the same order.
  • Your tables have to be deleted and built in correct order to not violate any foreign key constraints, otherwise the backup could fail.
  • Test extensively (ideally on a dedicated test system with a copy of your live data) with different scenarios (some or all tables empty, tables with lots of rows, all tables non-empty etc.) to ensure that it works reliably and that your backup script does not run out of memory due to a low memory_limit setting). Compare the destination database with the source by dumping them e.g. with mysqldump or the like to verify that they are identical and that the backup is complete. You might even encounter nasty PDO bugs in the worst case that you may need to work around – Google and SO are your friends :-).

EDIT:
One could additionally use the special INFORMATION_SCHEMA database to query the table names and determine the foreign key dependencies automatically.
Also, you might want to disable foreign key checks on the target database during transfer (and reenable them afterwards) when you have self-referential foreign key relations to prevent failures due to constraint violations.

情话难免假 2024-10-02 02:27:54

如果涉及备份,您应该真正坚持使用现有的管理工具。使用 SQLBuddy 或 PHPMySQLAdmin。

您可以使用 RPC 方法或使用 JSON 等数据传输来编写复制系统。但这需要保护,速度会很慢,并且只对内容传输有帮助,对 SQL 模式复制没有帮助。

If it's about having a backup, you should really stick to established admin tools. Use SQLBuddy or PHPMySQLAdmin.

You could write a duplication system using a RPC method or data transfer with JSON or something. But that needs securing, would be slow and only helpful for content transfer, not SQL schema replication.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文