2010-09-25 66 views
2

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

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

有什么简单的方法吗?

+0

为什么你需要使用PHP来完成这样的任务?是否没有shell可以访问你的MySQL服务器? – 2010-09-25 22:17:59

+0

这可能有合法的用途。我能想到的最重要的是平台独立性。如果你编写的软件要部署在多个系统上,这可能会降低支持成本(当然如果它有效的话)。但我同意,如果你在谈论一个单一的系统,请使用专门为此目的而编写的工具。它更快速,可靠并经过了充分测试。 – Archimedix 2010-09-25 22:49:20

+0

是的,我需要完整的平台独立性。我需要为几个网站的应用程序。有些服务器没有启用shell_exec,有些在安全模式下运行,basedir。我知道我应该使用mysql转储,但这是不可能的。我想到创建每个网站帐户到我的MySQL服务器和“同步”用户数据库与我的。我知道,通过互联网的MySQL不是很快,但对于备份...看起来像完美的解决方案。复制是不可能的,因为最终用户无权创建数据库。 – marc 2010-09-26 07:08:45

回答

0

如果是关于备份,你应该坚持建立管理工具。使用SQLBuddy或PHPMySQLAdmin。

您可以使用RPC方法编写复制系统或使用JSON或其他方式编写数据传输。但是这需要安全保护,速度很慢,只对内容传输有帮助,而不是SQL模式复制。

1

您必须对源数据库中的每个表执行,然后在目标数据库上运行一个大事务,删除所有先前的表数据,然后插入新数据。

<?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(如主键标识)不会造成错误,并在array_map()正常工作,所以$destDB->quote()应那么安全,但我不知道这是否适用于所有数据类型和所有数据库系统。
  • 在单个事务中执行所有操作可防止备份不一致。
  • 该示例假定您在两个数据库中都具有相同的数据库结构,并且所有列都以的顺序出现,完全相同的顺序
  • 必须删除您的表并按正确顺序构建,以免违反任何外键约束,否则备份可能会失败。
  • 用不同的场景(一些或全部表为空,表中有很多行,所有表非空等)广泛测试(理想情况下在一个专用测试系统上有一个实时数据副本),以确保它可靠工作,并且由于memory_limit setting较低,您的备份脚本不会耗尽​​内存)。比较目标数据库和源数据库用mysqldump等来验证它们是否相同并且备份是否完成。在最糟糕的情况下,您甚至可能会遇到令人讨厌的PDO错误,您可能需要解决Google和SO是–的问题:-)。

编辑:
人们可以另外使用特殊INFORMATION_SCHEMA database查询表名和自动判断外键依赖。
另外,如果您有自我引用的外键关系以防止由于违反约束条件导致的失败,您可能希望在传输期间在目标数据库上使用disable foreign key checks(并在之后重新启用它们)。