Mysql

如何在兩個 RDS MySQL 數據庫之間同步數據

  • October 4, 2013

我有 2 個 Amazon RDS MySQL 實例,一個是 MySql v5.5,一個是 5.6。我想將 5.5 升級到 5.6,但此時您無法進行升級,因此我們正在嘗試遷移數據。我做了 5.5 的轉儲並將轉儲導入 5.6,但由於我需要將停機時間降至最低,我決定嘗試在兩者之間進行數據同步。

我有什麼選擇?

  • 我有幾張很大的桌子!(1-8GB)
  • 表都是innodb
  • 轉儲下載耗時 3 小時
  • 轉儲上傳花了 4 個多小時

我需要盡量保持在 5 小時以下!

RDS for MySQL 5.6 支持使用 MySQL 的本機複製的實時工作負載的“in”和“out”遷移策略,但 RDS for MySQL 5.5,它們只支持“in”遷移……這是不幸的,因為基本上所有可能的組合除了一個你需要的是可用的。那會很好。:(

如果您的轉儲下載花費了 3 個小時,而您的上傳花費了 4 個多小時,那麼好消息是,您只需要 4 個多小時,因為您可以同時執行它們……並且取決於您是從 EC2 還是從 EC2 進行測試您自己的網路,可能更快。

我建議mysqldump使用mysql管道,這樣您就可以同時從舊伺服器讀取並寫入新伺服器。但是,為了使這項工作正常工作,我們需要添加一些曲折。然後幾個額外的曲折使它幾乎很有趣。

我認為您的理想方案是在同一區域的 EC2 中啟動一台一次性 linux 機器,其中您還沒有可用的機器……最好是與您的伺服器相同的可用區域,因為這將提供您可以在所涉及的 3 個組件中獲得最大的潛在頻寬,這就是減慢您速度的一件事。

接下來,在數據來自的源伺服器上,您需要發出SET GLOBAL NET_WRITE_TIMEOUT = 600;. 當然,您幾乎無法SET GLOBAL在 RDS 上進行任何操作,因此您必須通過 RDS 參數組進行更改。 NET_WRITE_TIMEOUT是 MySQL 伺服器在中止嘗試寫入阻塞的客戶端之前等待的時間量。當您將轉儲的輸出直接傳送到另一台伺服器時,目標伺服器將定期阻塞,有時阻塞時間超過預設的 60 秒。有一個伴隨變數 ,NET_READ_TIMEOUT您可能希望將其設置為類似的值,儘管我認為該變數在轉儲環境中沒有任何相關性。這將防止源伺服器在目標伺服器花費太長時間來執行大規模插入之一時超時mysqldump建構。如果您有MyISAM表格,則需要將其設置得更高,因為在ALTER TABLE ... ENABLE KEYS目標上完全恢復表格後,它可能需要永遠執行……但希望您不會。

值“600”(10 分鐘)有點隨意,但它是我用於此類操作的值。

就像mysqldump從遠端伺服器讀取並寫入管道到mysql命令行客戶端一樣,當mysql向目標發送大插入時,它會停止從管道讀取,從而阻止mysqldump寫入管道,進而阻止mysqldump從管道讀取直到目標伺服器準備好接收更多數據。除了這導致的超時之外,它還因為幾個不同的原因浪費了大量時間……mysqldump花費大量時間發現表結構並啟動其SELECT *查詢,我們希望避免所有這些浪費的時間。dd這樣做的原因是使用 unix實用程序設置雙緩衝區。

如果我們呼叫 dd 指定一個大的輸出塊大小而不指定輸入塊大小,它將從其輸入中讀取一個小塊大小(預設為 512 字節),直到它讀取其輸出塊大小指定的數據量,然後阻塞它的輸入並在一次大規模寫入中將該數據刷新到其輸出中。

dd obs=16384K

這將導致 dd 盡可能快地接受 16 MB 的數據,然後,一旦它可以將該塊刷新到其輸出,它將接受更多。

如果我們堆疊其中兩個,我們會得到一個雙緩衝區。:)

mysqldump [options] | dd obs=16384K | dd obs=16384K | mysql [options]

使用這種結構,我們可以始終將 16 到 32 兆字節的數據保存在 RAM 中,隨時在源伺服器和目標伺服器之間傳輸……所以我們基本上可以保證,只要目標伺服器準備好對於數據,我們可以立即為它準備好數據,而無需等待源……並且源可以保持忙碌,保持我們的緩衝區已滿。

16 MB 並不是真正的大量數據,因此甚至可能需要更大的緩衝區,但我們不想讓這些太大,因為當它們都已滿時,源端必須等到目標端可以在第一個緩衝區可以刷新到第二個緩衝區之前從第二個緩衝區讀取整個 16 MB,這會導致第一個緩衝區解除阻塞並開始接受來自源的更多數據……但是,如果需要,我們可以通過連結保持更多數據在飛行中dd的更多副本。它們將使用 100% 的指定記憶體,但使用的 CPU 很少。我通常連結其中至少 4 個。

順便說一句,如果您在其中插入一些 dd ,同樣的 hack 還將為您提供更快的 mysqldump-pipe-to-gzip(bzip、xz 等),因為它顯著增加了您始終擁有可用數據的可能性您的壓縮程序繼續執行,保持壓縮程序的處理器使用率最大化,這意味著更快的完成,因為由於充分的處理器使用率,壓縮可以在更少的掛鐘時間內完成。

您還應該--compress在兩者上都使用該選項mysqldumpmysql以便數據在兩個方向上通過線路壓縮。壓縮不是免費的,但這種壓縮只是 zlib 膨脹/放氣,所以它對 CPU 本身來說並不是一個非常重要的成本。正如您所指出的,像這樣的操作中最慢的部分是在目的地上,而目的地所要做的就是成本較低的減壓。

添加--verbose選項,mysqldump以便您可以觀察數據流動。

而且,為了增加一點甜味,幾個吞吐量米:

$ sudo apt-get install pv

這將允許您通過類似於此範例的終端上的輸出來密切關注程序:

inbound:  128MB 0:07:02 [    0B/s] [ 364kB/s] 
outbound:   96MB 0:06:00 [ 154kB/s] [ 334kB/s]

如果您知道您的轉儲大約有多大,您可以使用其他選項來pv提示該大小,它將以百分比計算進度。

您的最終命令如下所示(為單行,為清楚起見,此處格式化為多行):

mysqldump --compress --verbose [other options] |
pv -pterabc -N inbound |
dd obs=16384K | 
dd obs=16384K | 
dd obs=16384K | 
dd obs=16384K | 
pv -pterabc -N outbound |
mysql --compress [other options]

$$ other options $$當然是您在進行先前還原時與 mysqldump 和 mysql 客戶端一起使用的常用身份驗證憑據和其他選項。


如果您有多個模式或想要以其他方式執行並行副本的麻煩mysqldump | mysql可能值得一試以減少總時間,以及……恢復時間是目標伺服器上 CPU 和 IO 容量的乘積,並且使用 RDS,您似乎可能會看到兩個並行執行緒的組合吞吐量比 1 個執行緒快。

認為RDS 還有一個官方支持的選項,可以在恢復轉儲文件時暫時禁用二進制日誌記錄。您也可以對此進行探索,因為它可能會縮短恢復時間……只要您在完成後重新打開它。

引用自:https://dba.stackexchange.com/questions/50753