web-dev-qa-db-ja.com

ダウンタイムがほとんどまたはまったくない、非常に大きなmysqlテーブルの列の変更

私は定期的にmysql 5.1のテーブルに変更を加える必要があり、主に列を追加しています。 alter tableコマンドを使用すると、非常に簡単です。しかし、私のテーブルには現在最大4,000万行あり、それらは急速に成長しています...したがって、これらのalter tableコマンドは数時間かかります。数か月後には、私が推測しているように数日かかります。

私はAmazon RDSを使用しているため、スレーブサーバーを操作してマスターに昇格させることはできません。だから私の質問は、最小限のダウンタイムでこれを行う方法があるかどうかです。もちろん、ユーザーがまだdbを使用できる場合は、数時間または数日かかる操作でもかまいません...列が追加されている間、少なくとも読み取ることはできますか?アプリが書き込もうとするとどうなりますか?挿入または更新しますか?それがすぐに失敗する場合、それは実際にはそれほど悪くはありません。ハングし、dbサーバーに問題を引き起こす場合、それは大きな問題です。

これはかなり一般的なスケーリングの問題である必要があります。誰もが列を追加する必要があります。通常、運用データベースに対して何が行われますか?スレーブ->マスター移行?

更新-私はinnodbストレージエンジンを使用していることを忘れていました

18
apptree

私は定期的にmysql 5.1のテーブルに変更を加える必要があり、主に列を追加しています。

しないでください。いえいえ。しないでください。 everが必要な場合は、非常にまれなはずです。

データが本当に最初から正規化されていると仮定すると、問題を解決する正しい方法は、ベーステーブルと1:1の関係を持つ新しいテーブルを追加することです(新しいテーブルでは必須ではありません)。

通常、列を定期的に追加する必要があることは、正規化されていないデータベースの指標です。スキーマが正規化されていない場合は、修正する必要がある問題です。

最後に、スキーマが本当に正規化されていて、本当に列を追加し続ける必要がある場合:

  1. データベースにタイムスタンプ列があること、またはデータベースがレプリケーションログを生成していることを確認してください
  2. テーブル(A)のコピー(B)を作成する
  3. 新しい列をBに追加します(これはmyisamで引き続きブロックされます)
  4. トランザクションを無効にする
  5. 元のテーブル(A)を別の名前に変更(バックアップ)
  6. 新しいテーブル(B)の名前を元のテーブル(A)の名前に変更します。
  7. レプリケーションログまたはバックアップテーブルから、操作の開始からトランザクションを再生します。
  8. トランザクションを有効にします。
10
symcbean

私は最近これをしなければなりませんでした。 Amazonが推奨したのは、Percona Toolkitを使用することでした。私はそれをダウンロードして、次のようなものを実行することができました:

./pt-online-schema-change h=databasenameHostName,D=databasename,t=tablename --recursion-method=none --execute --user username --password password --alter "MODIFY someColumn newDataType"

そしてそれは素晴らしい働きをします。プロセスに残っている時間を示します。

実際には、新しい列で新しいテーブルを作成し、既存のデータをコピーします。さらに、トリガーを作成して、新しいデータも新しいテーブルにプッシュされるようにします。次に、テーブルの名前を自動的に変更し、古いテーブルを削除すると、新しい列で稼働し、更新を待つ間ダウンタイムは発生しません。

12
efreedom

symcbean はいくつかの 確固たる推奨事項 を提供します。

質問に答えるために、影響を軽減する最も簡単で最良の方法は、複数のデータベースを複製することです。アクティブでのレプリケーションを停止する適切なフェイルオーバー手順を備えたデュアルマスター。アクティブに影響を与えることなく、非アクティブでの変更を可能にします。

this answer で詳しく説明した手順と同様の手順を使用して、単一のライブデータベースでこれを実行し、影響を最小限に抑えることができます。確かに、これはsymcbeanの説明と似ていますが、技術的な詳細が含まれています。タイムスタンプだけでなく、auto_incrementフィールドも使用できます。

最終的に、データセットが非常に大きくなる場合は、 [〜#〜] oltp [〜#〜][〜#〜] olap [〜#の間のアーカイブも考慮する必要があります。 〜] データベース。適切に設計すれば、トランザクションデータセットはそれほど大きくする必要はありません。

4
Warner

マニュアルから: http://dev.mysql.com/doc/refman/5.1/en/alter-table.html

ほとんどの場合、ALTER TABLEは元のテーブルの一時的なコピーを作成します。 MySQLは変更をコピーに組み込み、元のテーブルを削除して新しいテーブルの名前を変更します。 ALTER TABLEの実行中、元のテーブルは他のセッションから読み取ることができます。テーブルへの更新と書き込みは、新しいテーブルの準備ができるまで停止され、その後、更新が失敗することなく、新しいテーブルに自動的にリダイレクトされます。

だから、読書はうまくいきます。書き込みは停止しますが、後で実行されます。これを防ぐには、ソフトウェアを変更する必要があります。

2
user22656

ほぼ65GBのトランザクションテーブルの1つを変更する必要がある同様の状況にあります。 2つの解決策を聞く

  1. 単純なALTERを使用して実行します(X時間または1日)
  2. データベースにタイムスタンプ列があること、またはデータベースがレプリケーションログを生成していることを確認してください
    • テーブル(A)のコピー(B)を作成する
    • 新しい列をBに追加します(これはmyisamで引き続きブロックされます)
    • トランザクションを無効にする
    • 元のテーブル(A)を別の名前に変更(バックアップ)
    • 新しいテーブル(B)の名前を元のテーブル(A)の名前に変更します。
0
user144107