2010-08-19 107 views
0

我遇到輕微問題。故事如下:從客戶端到主服務器同步mysql表數據

我有一個文件存檔系統(用PHP編寫),運行在多個客戶端(目前有23個)。在他們的系統上他們只有他們的文件。每天晚上,他們都需要「同步」到現場的主數據庫(中央服務器)。我可以從中央服務器訪問每個MySQL數據庫,因此連接到它們是沒有問題的。

我有一個連接到客戶端數據庫的腳本,選擇從同步列='0000-00-00 00:00:00'(默認表示它沒有同步)的表中的所有條目。然後,我會遍歷每條記錄,將其插入到中央服務器,並將客戶端數據庫記錄上的同步時間設置爲執行腳本的時間。這種方式很有效,但顯然在多個查詢中有很大的開銷,我現在剛剛注意到了這些問題。

每個客戶端每天可以生成多達2000 - 3000個奇數文檔。有了這些大數字,它會花費太長時間(1秒/ 2文檔)。

有沒有更好的解決我的問題?最好是一個PHP腳本解決方案,因爲我需要做日誌來檢查一切是否成功。

感謝

編輯: 我現在的流程是:

  1. 選擇所有未同步數據
  2. BEGIN TRANSACTION
  3. 插入記錄到中央數據庫服務器
  4. 選擇來自客戶端的文檔記錄
  5. 將文檔到中央數據庫服務器
  6. 更新同步列在客戶端
  7. 更新同步列在服務器上
  8. 提交交易

這是中央服務器上運行的腳本。 現在我想到了,我可以刪除第7步並將其作爲第5步的一部分,但這不會大大減少處理時間。

回答

1

我建議使用auto_increment_increment來保持所有服務器上的唯一id。然後,你需要做的只是一個SELECT * FROM blah WHERE sync = '0000-00-00 00:00:00',然後生成插入語句並執行它們。您不必處理任何衝突解決衝突的主鍵...

至於長查詢時間,你需要看看你的數據的大小。如果每條記錄都很大(幾百kb +),則需要花費時間...

一個選項可能是爲每個子服務器的表創建一個federated表。然後在master上執行SQL中的所有內容。 INSERT INTO master_table SELECT * FROM child_1_table WHERE sync = '0000-00-00 00:00:00' ...你可以避免把所有的數據都放到PHP中。你仍然可以運行一些檢查,以確保一切順利,並且你仍然可以登錄,因爲一切仍然是從PHP域執行的...

+0

這個ID不是問題。那些不需要同步。我通過其他各欄獲得正確的記錄。我只是使用ID將docarch_printout(關於文檔的所有細節)錶鏈接到docarch_printout_docs表(1 - 1僅包含文檔)。另一個問題是我們沒有永久連接到客戶端。有些撥打按需ISDN線路。由於這一點,我不認爲聯邦表會起作用。不錯的想法壽,從來不知道MySQL有這樣的選擇。 – Skippy 2010-08-19 11:25:05

+0

好吧,我想你可以在程序中存儲聯邦表的create sql。然後,當您連接到客戶端時,運行創建腳本。然後在完成後放下它(所以它只在主動同步時使用連接)... – ircmaxell 2010-08-19 11:32:58

+0

正確。我非常喜歡這個想法。 Everythng似乎很棒,但是,我需要同步由id字段引用的2個表(1-1關係)。一個是細節,另一個是實際文檔。簡單地說,它只是一張桌子。對此有任何進一步的想法?謝謝。 – Skippy 2010-08-19 12:29:50

0

基本方法聽起來不錯 - 但花費0.5秒做一個操作是荒謬的過度 - 你通過網絡拉動了多少數據?整個圖像?你在做什麼其他的事情?在同步列上是否有索引?

您可以通過在數據庫上做未同步數據的輸出得到一個小的好處:

1) mark all records available for sync with a transaction id in a new column 
2) extract all records flagged in first step into a flat file 
3) copy the file across the network 
4) load the data into the master DB 
5) if successful notify the origin server 
6) origin server then sets the sync time for all records flagged with that transaction id 

這將需要3個腳本 - 在源服務器上2(一個準備和發送數據,一個標記爲完成),另一個在複製服務器上輪詢數據並通知結果。

但是,如果您只是複製有關圖像(而不是圖像本身)的元數據,這可能不會大大侵入性能,看起來很荒謬。

C.

+0

用腳本逐步更新了我的初始文章,這樣您就可以看到我的邏輯 – Skippy 2010-08-19 14:15:41

+0

這仍然不能解釋爲什麼每個記錄需要0.5秒。由於事務不能跨越2個獨立的數據庫管理系統,因此它不會在此處添加任何值。記錄有多大? – symcbean 2010-08-19 21:18:18

+0

這是因爲客戶端通過ADSL(通過ISDN的幾個)連接到我們。記錄文件只有幾千字節的文字。 – Skippy 2010-08-20 05:53:30

0

我知道你喜歡一個基於PHP的解決方案,但你可能想看看微軟同步框架 -

http://msdn.microsoft.com/en-in/sync/default(en-us).aspx

這將需要被寫入同步模塊。但在同步邏輯和異常處理(網絡故障,同步衝突等)方面存在巨大的優勢,這將縮短您的時間。

只要存在.net的數據庫連接器,框架也會處理非sql服務器數據庫。 Mysql的應該很容易支持 - 只取一個樣品從以下鏈接 -

http://code.msdn.microsoft.com/sync/Release/ProjectReleases.aspx?ReleaseId=4835

和適應同到MySQL。

+0

這會很棒,但它必須在CentOS上運行。我們沒有任何微軟服務器 – Skippy 2010-08-20 05:47:32

+0

嗯..這是一個問題好吧..雖然它會很便宜,實際上只有一個人跑這個目的!我們實際上節省了大量的開發工作,所以您可以進行一些成本/收益分析並做出決定。 – 2010-08-20 06:05:07

0

即使世界,如果你不能使用同步框架另一種可能性 -

是否有可能爲你全天分配負載,而不是一天的結束?假設每次有10個新文檔進入或10次編輯完成時觸發同步? (如果同步是從客戶端發起的話,這可以完成)。

如果您希望將同步邏輯應用到服務器端,則無論客戶端何時需要同步,都可以考慮使用消息傳遞隊列將通知從客戶端發送到服務器。服務器然後可以提取數據。您可以使用內部服務總線或像azure appfabric/Amazon SQS這樣的按需平臺。

+0

存檔歸檔的文檔由其他應用程序在當天結束時生成。文件存檔系統監視目錄中的新文件,處理它等。因此,導入也是批量完成的。同步需要在一天結束時完成,以配合具有ISDN線路的客戶端連接到我們用於其他目的。 – Skippy 2010-08-20 08:23:20

+0

好的..因爲你已經有了一個可行的答案..乾杯! – 2010-08-20 09:04:29

相關問題