2008-09-22 88 views
0

我有一個數據庫,我打算複製出於備份的原因(性能目前不是問題)。複製大量的臨時表寫入

我們已經正確設置了複製並對其進行了測試,一切正常。

然後我們意識到它將所有的寫入複製到臨時表中,這實際上意味着一天數據量的複製花費了將近兩個小時的時間用於空閒的從站。

原因是我們每隔15分鐘通過cronjob重新計算db中的某些數據以確保它同步(總共需要大約3分鐘,因此在Web請求期間執行這些操作是不可接受的;相反,我們只是在Web請求中存儲修改而不嘗試重新計算任何內容,然後再批量執行所有工作)。爲了有效地處理這些數據,我們使用臨時表(因爲存在很多相互依賴關係)。

現在,第一個問題是,如果我們在處理使用該臨時表的事務的中間時重新啓動從屬服務器,臨時表不會持久存在。這可以通過不使用臨時表來避免,儘管這有其自身的問題。

更嚴重的問題是,如果不是所有的重新計算(它一個接一個地重新計算,所以沒有重建數據的好處每15分鐘... ...你可以從字面上看到它停留在,比如說1115,只是爲了快速追上並卡在1130等)。

我們提出的一個解決方案是將所有重新計算的數據移出複製數據庫,以便從站不復制它。但它的缺點在於我們不得不修剪它最終更新的表格,使得我們的奴隸實際上「閹割」,即。我們必須在實際使用它之前重新計算它上面的所有內容。

有沒有人有類似的問題和/或你會如何解決它?我錯過了明顯的東西嗎?

回答

2

我想出瞭解決方案。它使用Nick提到的replicate-do-db。寫下來以防有人遇到類似問題。

在這種情況下(就像我說過的,我們使用臨時表來重新填充一箇中央表),只是使用複製 - (wild-)do *選項的問題是,要麼忽略臨時表並重新填充沒有數據(這會導致進一步的問題,因爲所有依賴中央表的查詢都是最新的將產生不同的結果),或者忽略具有類似問題的中央表。更何況,你必須在添加任何這些選項到my.cnf後重新啓動mysql。我們希望能涵蓋所有這些情況(以及未來的情況),而無需進一步重啓。

因此,我們決定做的是將數據庫分爲「真實」和「工作區」數據庫。只有「真正的」數據庫被複制(我想你可以決定一個表名的慣例,用於複製 - 野外表語法)。

所有的臨時表工作都發生在「workarea」db中,爲了避免上面提到的依賴性問題,我們不會使用INSERT ... SELECT填充中央表(它位於「真實」數據庫中)或RENAME TABLE,而是查詢tmp表,以在活動表上生成一種diff(即,爲新行生成INSERT語句,爲舊行生成INSERT語句並在必要時進行更新)。

這樣,複製的唯一查詢就是所需的更新,沒有別的,也就是說。一些(大多數?)每15分鐘重新計算一次的查詢可能甚至無法通向slave,而那些只需簡單的INSERT和DELETE就可以達到最小的計算花費。

1

在MySQL中,我相信你可以通過表通配符來複制特定的表。有許多命令行選項可以設置,但你也可以通過你的MySQL配置文件來完成。

[mysqld] 
replicate-do-db = db1 
replicate-do-table = db2.mytbl2 
replicate-wild-do-table= database_name.% 
replicate-wild-do-table= another_db.% 

這個想法是你告訴它不復制除你指定的表以外的任何表。

+0

感謝您的支持,但它只是解決方案的一部分,因爲最終的表格(即,重新計算的臨時表格,而不是臨時的中間表格)是其他查詢成功運行所必需的,所以我們不能別理他們。 – tpk 2008-09-26 11:34:14