一個可行的方法:
在「源」服務器創建輸出表的內容在一個簡單的解析格式(XML想到作爲一個PHP腳本(以下簡稱「出口」)容易生成和消費,但像CSV這樣的替代品可以)。
在「目標」服務器上創建一個「導入器」PHP腳本,通過HTTP請求導出器,分析結果並使用該數據填充表格。
這是非常通用的,但應該讓你開始。這裏有一些注意事項:
- http://ie2.php.net/manual/en/function.http-request.php是你的朋友
- 如果表中包含敏感數據,有許多技術,增強的安全性(HTTP_REQUEST不會給你的https://直接支持,但你可以加密您導出的數據和導入時解密的數據:查看PHP手冊上的「SSL」以獲取更多詳細信息)。
- 您應該考慮添加一些冗餘(或者甚至全面加密的加密)以防止數據在服務器之間運行網頁時被篡改。
- 您可以使用GET參數來增加靈活性(例如,將表名作爲參數傳遞將允許您爲可能需要傳輸的所有表使用單個腳本)。
- 對於大型表格,PHP超時可能會對您發揮作用。對此的理想解決方案是導出和導入腳本的高效代碼+自定義超時,但我甚至不確定這是否可能。一個相當可靠的解決方法是以大塊的方式完成這項工作(GET PARAMS在這裏派上用場,告訴出口商你需要什麼塊,並且輸出上的特殊條目足以告訴導入器剩下多少要導入)。重定向對這種方法有很大的幫助(每個重定向都是一個新的請求,對服務器來說,所以超時被重置)。
也許我失去了一些東西,但我希望有足夠的存在,讓你得到你的手髒的工作,回來與任何具體的問題,我可能也沒有預見。
希望這會有所幫助。
編輯: 哎呀,我錯過了細節,無論是數據塊在同一臺服務器上。在這種情況下,您可以將導入和導出任務合併到一個腳本中。這意味着:
- 您不需要「傳輸」格式(如XML或CSV):PHP中的內存中表示就足夠了,因爲現在兩個任務都在同一個腳本中完成。
- 數據永遠不會離開您的服務器,因此對加密的需求並不那麼重。只要確保沒有其他人可以運行你的腳本(通過認證或類似的技術),你應該沒問題。
- 超時限制並不那麼嚴格,因爲您不會浪費很多時間等待從源到達目標服務器的響應,但它們仍然適用。塊處理,重定向和GET參數(在重定向的位置內傳遞)仍然是一個很好的解決方案,但由於執行時間度量標準比跨服務器數據傳輸度量標準更可靠,因此您可以更接近超時。
這裏是一個很粗糙草圖,你可能不得不代碼是什麼:
$link_src = mysql_connect(source DB connection details);
$link_dst = mysql_connect(destination DB connection details);
/* You may want to truncate the table on destination before going on, to prevent data repetition */
$q = "INSERT INTO `table_name_here` (column_list_here) VALUES ";
$res = mysql_query("SELECT * FROM `table_name_here`", $link_src);
while ($row = mysql_fetch_assoc($res)) {
$q = $q . sprintf("(%s, %s, %s), ", $row['field1_name'], $row['field2_name'], $row['field3_name']);
}
mysql_free_result($res);
/* removing the trailing ',' from $q is left as an exercise (ok, I'm lazy, but that's supposed to be just a sketck) */
mysql_query($q, $link_dst);
你必須添加的分塊邏輯在那裏(那些過於病例& setup-specific),並可能輸出一些確認消息(可能是DESCRIBE和COUNT的源表和目標表以及它們之間的比較?),但這是相當核心的工作。 作爲替代方案,您可以在每行中運行一個單獨的插入(在循環中調用查詢),但我確信單個查詢會更快(但是,如果您對PHP的RAM限制太小,則此替代方法可讓您擺脫渴望內存的$q
)。
另一個編輯:
張貼羅伯託的文檔鏈接:
如果你發送一個查詢,以不正確或過大的服務器也可以得到這些錯誤。如果mysqld收到的數據包太大或失序,則認爲客戶端出現問題並關閉連接。如果您需要大量查詢(例如,如果您使用大BLOB列),則可以通過設置服務器的max_allowed_packet變量(默認值爲1MB)來增加查詢限制。您可能還需要增加客戶端上的最大數據包大小。有關設置數據包大小的更多信息在第B.5.2.10節「數據包太大」中給出。
插入很多行的INSERT或REPLACE語句也會導致這類錯誤。無論要插入的行數是多少,這些語句中的任何一個都會向服務器發送一個請求;因此,您通常可以通過減少每個INSERT或REPLACE發送的行數來避免錯誤。
如果那是什麼造成您的問題(和你的問題似乎很可能它),然後打破INSERT到每行一個查詢的方法將最有可能解決這個問題。在這種情況下,上面的代碼草圖變爲:
$link_src = mysql_connect(source DB connection details);
$link_dst = mysql_connect(destination DB connection details);
/* You may want to truncate the table on destination before going on, to prevent data repetition */
$q = "INSERT INTO `table_name_here` (column_list_here) VALUES ";
$res = mysql_query("SELECT * FROM `table_name_here`", $link_src);
while ($row = mysql_fetch_assoc($res)) {
$q = $q . sprintf("INSERT INTO `table_name_here` (`field1_name`, `field2_name`, `field3_name`) VALUE (%s, %s, %s)", $row['field1_name'], $row['field2_name'], $row['field3_name']);
}
mysql_free_result($res);
該問題也可能由初始SELECT的大量觸發;在這種情況下,您應該將此與分塊(使用多個SELECT + while()塊,從SQL的LIMIT子句獲利或通過重定向)組合,從而將SELECT分解爲多個較小的查詢。 (請注意,只有在出現超時問題時才需要重定向分塊,或者如果表增長時您的執行時間已經足夠接近超時以解決問題,那麼無論如何實施它可能是個好主意,所以即使你的桌子長到一個淫穢的大小劇本將仍然工作不變。)
你用什麼來導出數據庫?你有SSH訪問服務器?你能用一個mySQL登錄看到兩個數據庫嗎? – 2010-03-28 21:18:45
不,沒有SSH訪問權限。我使用cPanel來做所有事情。 – Yeti 2010-03-28 21:25:52