2つのAmazon RDS MySQLインスタンスがあります。1つはMySql v5.5で、新しいインスタンスは5.6です。 5.5から5.6にアップグレードしたいのですが、現時点ではアップグレードできないため、データの移行を試みています。私は5.5のダンプを作成し、ダンプを5.6にインポートしましたが、ダウンタイムを最小限に抑える必要があるため、2つの間でデータ同期を試みることにしました。
これに対する私のオプションは何ですか?
合計5時間以内に滞在する必要があります。
RDS for MySQL 5.6は、MySQLのネイティブレプリケーションを使用したライブワークロードの「イン」および「アウト」 移行戦略 をサポートしますが、RDS for MySQL 5.5では、「イン」移行のみをサポートします...これは残念なことです。なぜなら、必要な組み合わせ以外のすべての可能な組み合わせが利用できるからです。それはニースだったでしょう。 :(
ダンプのダウンロードに3時間かかり、アップロードに4時間以上かかった場合、朗報は、4時間以上しか必要ないことです。これは、同時に実行できるためです。EC2からテストを実行したか、EC2からテストを実行したかによっておそらくより高速な独自のネットワーク。
私が提案するのは、パイプラインを使用してmysqldump
をmysql
に結び付けることです。これにより、古いサーバーからの読み取りと新しいサーバーへの書き込みを同時に行うことができます。ただし、これを適切に機能させるには、いくつかの工夫を加える必要があります。そして、2、3の余分な工夫がそれをほとんど楽しいものにします。
あなたの理想的なシナリオは、EC2の使い捨てのLinuxマシンを同じリージョンで起動することだと思います。まだ利用可能なものは1つもありません。サーバーと同じアベイラビリティーゾーンが望ましいです。これにより、関係する3つのコンポーネント間で最大の潜在的な帯域幅が得られます。これにより、速度が遅くなります。
次に、データの送信元サーバーで、SET GLOBAL NET_WRITE_TIMEOUT = 600;
を発行する必要があります。もちろん、RDSでSET GLOBAL
を行うことはほとんどできないため、RDSパラメータグループを使用してこれを変更する必要があります。 NET_WRITE_TIMEOUT
は、MySQLサーバーが、ブロックしているクライアントへの書き込みの試行を中止するまで待機する時間です。ダンプの出力を別のサーバーに直接パイプしている場合、宛先サーバーは定期的にブロックし、場合によってはデフォルトの60秒よりも長くブロックします。コンパニオン変数NET_READ_TIMEOUT
があります。これは、同様の値に設定する必要があるかもしれませんが、この変数はダンプ環境では関連性がないと思います。これにより、移行先サーバーがmysqldump
が構築する大量の挿入の1つを実行するのに時間がかかりすぎる場合に、移行元サーバーがタイムアウトするのを防ぎます。 MyISAM
テーブルがある場合、テーブルをターゲットで完全に復元した後、ALTER TABLE ... ENABLE KEYS
の実行に永久に時間がかかる可能性があるため、さらに高く設定する必要があります...しかし、うまくいけば、 。
「600」(10分)という値は多少不定ですが、私はこのような操作に使用しています。
mysqldump
はリモートサーバーから読み取り、パイプにmysql
コマンドラインクライアントに書き込みを行っているため、mysql
が宛先に大きな挿入を送信すると、宛先からの読み取りを停止しますパイプは、パイプへのmysqldump
の書き込みをブロックします。パイプは、宛先サーバーがさらにデータを受信できるようになるまで、ソケットからのmysqldump
の読み取りをブロックします。これにより引き起こされるタイムアウトに加えて、いくつかの異なる理由により、多くの時間を浪費します... mysqldump
は、テーブル構造の検出とSELECT *
クエリの開始に多くの時間を費やします。そのすべての無駄な時間。これのチケットは、unix dd
ユーティリティを使用してダブルバッファを設定することです。
入力ブロックサイズを指定せずに大きな出力ブロックサイズを指定してddを呼び出すと、出力ブロックサイズで指定された量のデータを読み取るまで、小さなブロックサイズ(デフォルトは512バイト)で入力から読み取り、次にブロックします。入力とそのデータを1回の大量書き込みで出力からフラッシュします。
dd obs=16384K
これにより、ddは16 MBのデータをフィードできる限り速く受け入れるようになり、そのブロックを出力にフラッシュできるようになると、さらに多くを受け入れます。
それらの2つをスタックすると、ダブルバッファーが取得されます。 :)
mysqldump [options] | dd obs=16384K | dd obs=16384K | mysql [options]
この構造を使用すると、起点サーバーと宛先サーバー間で常に16〜32メガバイトのデータをRAMに保持できます。そのため、宛先サーバーの準備ができるとすぐに、データについては、Originを待たずにすぐにデータを準備できます...そして、Originはバッファをフルに保ちながらビジー状態を維持できます。
16 MBは実際には大量のデータではないため、さらに大きなバッファーが望ましい場合がありますが、これらを大きくしすぎないようにしてください。両方がいっぱいになると、Originは宛先ができるまで待機する必要があるためです。 1番目のバッファーが2番目のバッファーにフラッシュされる前に2番目のバッファーから16 MB全体を読み取ると、1番目のバッファーのブロックが解除され、Originからより多くのデータを受け入れ始めるようになります... ddのさらに多くのコピー。指定されたメモリを100%使用しますが、CPUはほとんど使用しません。私は通常それらの少なくとも4つをチェーンします。
ちなみに、この同じハックでは、間にddを挿入すると、mysqldump-pipe-to-gzip(bzip、xzなど)も高速になります。これにより、常にデータを利用できる可能性が大幅に高まります。圧縮プログラムをクランチし、圧縮プログラムのプロセッサー使用率を最大に保ちます。これは、完全なプロセッサー使用率のためにクランチが少ない実時間で行われるため、完了が速くなることを意味します。
また、mysqldump
とmysql
の両方で--compress
オプションを使用して、データがネットワーク経由で双方向に圧縮されるようにする必要があります。圧縮は無料ではありませんが、この圧縮は単にzlib inflate/deflateなので、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]
[その他のオプション]は、通常の認証資格情報と、前回の復元時にmysqldumpおよびmysqlクライアントで使用したその他のオプションです。
複数のスキーマがある場合、または別の方法でmysqldump | mysql
の並列コピーを実行する問題に行きたい場合は、合計時間を短縮することも一考に値するかもしれません...復元時間は、CPUとIO宛先サーバーの容量、およびRDSでは、2つの並列スレッドの合計スループットが1スレッドよりも高速であるように見えるかもしれません。
IthinkRDSには、ダンプファイルの復元中にバイナリログを一時的に無効にする公式のサポートされているオプションもあります。復元時間を改善する可能性があるので、それを探索することもできます...完了時にオンに戻す限り。