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


18

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

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

これはかなり一般的なスケーリングの問題である必要があり、誰もが列を追加する必要があります。スレーブ->マスター移行?

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


1
誰かがまだ答えを探している場合..blog.staginginstance.com/… ^^
コーダー匿名

回答:


10

私は定期的にmysql 5.1のテーブルを変更する必要があり、ほとんどの場合は列を追加します。

しないでください。いやいや。しないでください。これがあるとき、それは非常にまれである必要があり、これまで必要。

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

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

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

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

2
一歩一歩アプローチしていただきありがとうございます。テーブルを変更することは本当にまれですか?代わりに、新しい列を持つ別のテーブルを追加し(列を追加する必要がある場合)、1対1の関係で元の大きなテーブルを参照できることを理解しています。しかし、それらがすべて1つのテーブルにある場合、15の非常に大きな1:1テーブルを持つのは正しくないと思われます...インデックス作成の問題は言うまでもなく、当然クエリのパフォーマンスも低下します。私は専門家ではありませんが、私のデータベースはかなり正常に正規化されており、定期的に変更する必要があるのは自然なことです
。– apptree

2
「テーブルを変更するのは本当に珍しいことですか?」- はい。
symcbean

1
いいえ、しかし、メジャーなソフトウェアアップグレードの一部としてではなく、定期的にそれが発生した場合、すべてのテーブルがそもそもそこにあることに気付かないために誰かを解雇する必要があると主張することができます。ここでの問題/トリックは、「数か月に一度」ではなく「定期的に」です。
トムトム14年

22
開発者、特に新興企業や若い企業で働く開発者として、私はsymcbeanと@TomTomにはあまり同意できませんでした。物事は変化し、製品は変化し、ビジネス目標は変化し、データベース構造はそれらとともに変化する必要があります。適切なDBAサービスを提供するということは、それらの変更に「はい」と言ってから、それらを効率的に実装する方法を見つけ出すことです。高度に正規化されたデータベースは、ずっと前に消滅した概念です。その結果、パフォーマンスが低下し、開発サイクルが遅くなります。
pents90

4
テーブルを変更するのは珍しい??? 多分大企業でも、頻繁に起こるアジャイルチームでは、要件が変わります
...-tibo

12

私は最近これをしなければなりませんでした。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"

そしてそれはうまく機能します。プロセスの残り時間がわかります。

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


Perconaチームは、pt-online-schema-changeツールで必要なRDSパラメーターグループ(SET GLOBAL log_bin_trust_function_creators = 1はRDSでは機能しないため)を介して、log_bin_trust_function_creators機能を有効にすることについて簡単に説明しています。詳細:percona.com/blog/2016/07/01/pt-online-schema-change-amazon-rds
user1652110

その私のために働いた
Adiii

4

symcbeanは、いくつかの確実な推奨事項を提供します。

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

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

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


2

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

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

したがって、読み取りは正常に機能します。書き込みは停止しますが、その後実行されます。これを防ぐには、ソフトウェアを変更する必要があります。


そのため、これを実行し、現在変更中のテーブルに書き込むサイトの部分を無効にしました。これまでに、いくつかの「ロック待機タイムアウトを超えました;トランザクションを再開してみてください」という例外を受け取りましたが、それはそれほど悪くはありません。ただし、それらは
純粋に

0

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

  1. 単純なALTERを使用して実行します(X時間または1日)
  2. データベースにタイムスタンプ列があること、またはレプリケーションログを生成していることを確認してください
    • テーブル(A)のコピー(B)を作成します
    • Bに新しい列を追加します(これはmyisamでブロックされます)
    • トランザクションを無効にする
    • 元のテーブル(A)を別の名前に変更(バックアップ)
    • 新しいテーブル(B)の名前を元のテーブル(A)の名前に変更します
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.