2010-09-25 109 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(並在之後重新啓用它們)。