sql >> データベース >  >> RDS >> MariaDB

MySQLとMariaDBのスキーマ管理のヒント

    データベーススキーマは、石で書かれたものではありません。特定のアプリケーション向けに設計されていますが、要件は変更される可能性があり、通常は変更されます。新しいモジュールと機能がアプリケーションに追加され、より多くのデータが収集され、コードとデータモデルのリファクタリングが実行されます。そのため、これらの変更に適応するためにデータベーススキーマを変更する必要があります。列の追加または変更、新しいテーブルの作成、または大きなテーブルのパーティション化。開発者がユーザーがデータを操作するための新しい方法を追加すると、クエリも変化します。新しいクエリでは、新しい、より効率的なインデックスを使用できるため、アプリケーションに最高のデータベースパフォーマンスを提供するために、急いでインデックスを作成します。

    では、スキーマの変更にどのようにアプローチするのが最善でしょうか?どのようなツールが便利ですか?本番データベースへの影響を最小限に抑える方法は?スキーマ設計で最も一般的な問題は何ですか?スキーマを常に把握するのに役立つツールは何ですか?このブログ投稿では、MySQLとMariaDBでスキーマを変更する方法の概要を説明します。 GaleraClusterのコンテキストではスキーマの変更については説明しないことに注意してください。以前のブログ投稿で、RSUの影響を最小限に抑えるための全順序の分離、ローリングスキーマのアップグレード、およびヒントについてはすでに説明しました。また、スキーマ設計に関連するヒントとコツ、およびClusterControlがすべてのスキーマ変更を把握するのにどのように役立つかについても説明します。

    スキーマ変更の種類

    まず最初に。トピックを掘り下げる前に、MySQLとMariaDBがスキーマの変更をどのように実行するかを理解する必要があります。ご覧のとおり、あるスキーマの変更は別のスキーマの変更と同じではありません。

    オンライン変更、インスタント変更、またはインプレース変更について聞いたことがあるかもしれません。これはすべて、本番データベースへのスキーマ変更の影響を最小限に抑えるために進行中の作業の結果です。歴史的に、ほとんどすべてのスキーマ変更がブロックされていました。スキーマの変更を実行した場合、ALTERが完了するのを待って、すべてのクエリが積み重なっていきます。明らかに、これは本番環境の展開に深刻な問題を引き起こしました。確かに、人々はすぐに回避策を探し始めます。今日でもそれらはまだ関連しているので、このブログの後半でそれらについて説明します。しかしまた、他のクエリに大きな影響を与えることなくDDL(データ定義言語)を実行するMySQLの機能を改善するための作業が開始されました。

    即時の変更

    変更する必要があるのはメタデータだけであるため、テーブルスペース内のデータに触れる必要がない場合もあります。ここでの例は、インデックスの削除や列の名前の変更です。このような操作は迅速かつ効率的です。通常、それらの影響は限定的です。ただし、影響がないわけではありません。メタデータの変更を実行するのに数秒かかる場合があり、そのような変更にはメタデータロックを取得する必要があります。このロックはテーブルごとに行われ、このテーブルで実行される他の操作をブロックする可能性があります。これは、プロセスリストの「テーブルメタデータロックを待機しています」エントリとして表示されます。

    このような変更の例としては、MariaDB10.3およびMySQL8.0で導入されたインスタントADDCOLUMNがあります。これにより、この非常に人気のあるスキーマ変更を遅滞なく実行できるようになります。 MariaDBとOracleの両方が、テーブルに新しい列を即座に追加できるTencentGameのコードを含めることにしました。これは特定の条件下にあります。列は最後の列として追加する必要があります。フルテキストインデックスはテーブルに存在できず、行形式は圧縮できません。インスタント追加列の動作の詳細については、MariaDBのドキュメントを参照してください。 MySQLの場合、公式ドキュメントを更新するためのバグが存在しますが、公式リファレンスはmysqlserverteam.comブログでのみ見つけることができます。

    インプレース変更

    一部の変更では、表領域のデータを変更する必要があります。このような変更はデータ自体に対して実行でき、新しいデータ構造で一時テーブルを作成する必要はありません。このような変更は、通常(常にではありませんが)、スキーマ変更の実行中にテーブルにアクセスする他のクエリを実行できるようにします。このような操作の例は、テーブルに新しいセカンダリインデックスを追加することです。この操作の実行には時間がかかりますが、DMLを実行できるようになります。

    テーブルの再構築

    その場で変更を加えることができない場合、InnoDBは新しい必要な構造で一時テーブルを作成します。次に、既存のデータを新しいテーブルにコピーします。この操作は最もコストのかかる操作であり、DMLをロックする可能性があります(常に発生するとは限りませんが)。その結果、このようなスキーマの変更は、外部ツールを使用せずにスタンドアロンサーバーの大きなテーブルで実行するのは非常に困難です。通常、データベースを長時間または数時間ロックする余裕はありません。このような操作の例は、列のデータ型をたとえばINTからVARCHARに変更することです。

    スキームの変更とレプリケーション

    さて、InnoDBではオンラインスキーマ変更が許可されていることがわかっています。MySQLのドキュメントを参照すると、スキーマ変更の大部分(少なくとも最も一般的なものの中で)をオンラインで実行できることがわかります。 gh-ostのようなオンラインスキーマ変更ツールを作成するために開発に何時間も費やした理由は何ですか? pt-online-schema-changeは古くて悪い時代の名残であると認めることができますが、gh-ostは新しいソフトウェアです。

    答えは複雑です。主な問題は2つあります。

    手始めに、スキーマの変更を開始すると、それを制御することはできません。中止することはできますが、一時停止することはできません。あなたはそれを絞ることはできません。ご想像のとおり、テーブルの再構築はコストのかかる操作であり、InnoDBでDMLの実行が許可されている場合でも、DDLからの追加のI / Oワークロードは他のすべてのクエリに影響し、この影響を許容できるレベルに制限する方法はありません。アプリケーション。

    第二に、さらに深刻な問題は複製です。テーブルの再構築が必要な非ブロッキング操作を実行する場合、実際にはDMLはロックされませんが、これはマスターにのみ当てはまります。このようなDDLの完了に30分かかったと仮定します。ALTERの速度はハードウェアによって異なりますが、20GBのサイズ範囲のテーブルでこのような実行時間が見られることはかなり一般的です。次に、すべてのスレーブに複製され、それらのスレーブでDDLが開始された瞬間から、複製はそれが完了するのを待ちます。 MySQLまたはMariaDBを使用するかどうか、またはマルチスレッドレプリケーションを使用するかどうかは関係ありません。スレーブは遅れます-残りのbinlogイベントの適用を開始する前に、DDLが完了するまで30分間待機します。ご想像のとおり、30分のラグ(30秒でも受け入れられない場合があります。すべてアプリケーションによって異なります)は、これらのスレーブをスケールアウトに使用することを不可能にするものです。もちろん、回避策があります。レプリケーションチェーンの最下位から最上位までスキーマの変更を実行できますが、これによりオプションが大幅に制限されます。特に行ベースのレプリケーションを使用する場合は、互換性のあるスキーマ変更のみをこの方法で実行できます。行ベースのレプリケーションの制限の例のカップル。最後の列以外の列を削除したり、最後の列以外の位置に列を追加したりすることはできません。列タイプを変更することもできません(たとえば、INT-> VARCHAR)。

    ご覧のとおり、レプリケーションにより、スキーマの変更を実行する方法が複雑になります。スタンドアロンホストで非ブロッキングである操作は、スレーブで実行されている間はブロッキングになります。スキーマ変更の影響を最小限に抑えるために使用できるいくつかの方法を見てみましょう。

    オンラインスキーマ変更ツール

    前述したように、スキーマの変更を実行することを目的としたツールがあります。最も人気のあるものは、Perconaによって作成されたpt-online-schema-changeとGitHubによって作成されたgh-ostです。一連のブログ投稿で、それらを比較し、gh-ostを使用してスキーマの変更を実行する方法と、実行中の移行を抑制および再構成する方法について説明しました。ここでは詳細については説明しませんが、これらのツールを使用する上で最も重要な側面のいくつかについて説明します。手始めに、pt-oscまたはgh-ostを介して実行されるスキーマ変更は、すべてのデータベースノードで一度に発生します。変更が適用される時期に関しては、遅延は一切ありません。これにより、行ベースのレプリケーションと互換性のないスキーマ変更に対しても、これらのツールを使用できるようになります。これらのツールがテーブルの変更を追跡する方法に関する正確なメカニズムは異なりますが(pt-oscでのトリガーとgh-ostでのbinlog解析)、主な考え方は同じです。新しいテーブルが目的のスキーマで作成され、既存のデータは古いテーブルからコピーされました。その間、DMLは(いずれかの方法で)追跡され、新しいテーブルに適用されます。すべてのデータが移行されると、テーブルの名前が変更され、新しいテーブルが古いテーブルに置き換わります。これはアトミック操作であるため、アプリケーションには表示されません。どちらのツールにも、負荷を抑制して操作を一時停止するオプションがあります。 Gh-ostはすべてのアクティビティを停止でき、pt-oscは古いテーブルと新しいテーブルの間でデータをコピーするプロセスのみを停止できます。トリガーはアクティブなままで、データの複製を続行するため、オーバーヘッドが追加されます。テーブルの名前変更のため、両方のツールには外部キーに関するいくつかの制限があります-gh-ostでサポートされていないか、通常のALTERを介してpt-oscで部分的にサポートされているため、レプリケーションの遅延が発生する可能性があります(子テーブルが大きい場合は実行できません)。新しいテーブルの名前を変更する前に古いテーブルを削除します-何らかの理由でデータが新しいテーブルに正しくコピーされなかった場合、ロールバックする方法がないため、危険です。トリガーもサポートするのが難しいです。

    これらは、MySQL 5.7のgh-ost、pt-oscではサポートされておらず、新しいものでは、既存のトリガーを持つテーブルのサポートが制限されています。オンラインスキーマ変更ツールのその他の重要な制限は、一意のキーまたは主キーがテーブルに存在する必要があることです。これは、古いテーブルと新しいテーブルの間でコピーする行を識別するために使用されます。これらのツールは、直接のALTERよりもはるかに低速です。ALTERの実行中に数時間かかる変更は、pt-oscまたはgh-ostを使用して実行すると数日かかる場合があります。

    一方、前述したように、要件が満たされ、制限が適用されない限り、ツールの1つを使用してすべてのスキーマ変更を実行できます。すべてがすべてのホストで同時に発生するため、互換性について心配する必要はありません。また、プロセスの実行方法をある程度制御することもできます(pt-oscでは少なく、gh-ostでははるかに多くなります)。

    スキーマ変更の影響を減らし、一時停止して監視下でのみ実行させることができ、実際に実行する前に変更をテストできます。影響が検出された場合に、レプリケーションの遅延と一時停止を追跡することができます。これにより、これらのツールは、MySQLレプリケーションを操作する際に、DBAの武器に非常に優れたものになります。

    ローリングスキーマの変更

    通常、DBAはオンラインスキーマ変更ツールの1つを使用します。ただし、前に説明したように、状況によっては使用できず、直接変更することが唯一の実行可能なオプションです。スタンドアロンのMySQLについて話している場合、選択の余地はありません。変更が非ブロッキングである場合、それは良いことです。そうでなければ、まあ、それについてあなたができることは何もありません。しかし、それでは、MySQLを単一のインスタンスとして実行する人はそれほど多くありませんよね?レプリケーションはどうですか?前に説明したように、マスターを直接変更することはできません。ほとんどの場合、スレーブで遅延が発生し、これは受け入れられない可能性があります。ただし、実行できるのは、変更をローリング方式で実行することです。スレーブから始めて、すべてのスレーブに変更が適用されたら、スレーブの1つを新しいマスターとして昇格させ、古いマスターをスレーブに降格させて、その上で変更を実行します。もちろん、変更には互換性が必要ですが、実を言うと、オンラインスキーマの変更を使用できない最も一般的なケースは、主キーまたは一意キーがないためです。他のすべての場合、特にpt-online-schema-changeでは、gh-ostにはより厳しい制限があるため、何らかの回避策があります。これは、「そうそう」または「理想からはほど遠い」と呼ぶ回避策ですが、他に選択肢がない場合は機能します。また重要なことは、テーブルが大きくなる前にスキーマを監視して問題をキャッチすれば、ほとんどの制限を回避できることです。誰かが主キーなしでテーブルを作成したとしても、テーブルはほとんど空なので、0.5秒以下かかる直接変更を実行しても問題はありません。

    それが大きくなると、これは深刻な問題になりますが、実際に問題が発生し始める前に、この種の問題をキャッチするのはDBAの責任です。このような問題を時間どおりに確実にキャッチするためのヒントとコツをいくつか取り上げます。また、スキーマを設計する方法に関する一般的なヒントも共有します。

    ヒントとコツ

    スキーマデザイン

    この投稿で示したように、レプリケーションセットアップを操作する場合、オンラインスキーマ変更ツールは非常に重要です。したがって、スキーマ変更を実行するためのオプションが制限されないようにスキーマが設計されていることを確認することが非常に重要です。 3つの重要な側面があります。まず、主キーまたは一意キーが存在する必要があります。データベースに主キーのないテーブルがないことを確認する必要があります。これを定期的に監視する必要があります。そうしないと、将来深刻な問題になる可能性があります。次に、外部キーを使用することが良い考えであるかどうかを真剣に検討する必要があります。確かに、それらには用途がありますが、データベースにオーバーヘッドが追加され、オンラインスキーマ変更ツールの使用が問題になる可能性があります。関係は、アプリケーションによって実施できます。それがより多くの作業を意味するとしても、外部キーの使用を開始し、実行できるスキーマ変更のタイプに厳しく制限するよりも、それでも良い考えかもしれません。第三に、トリガー。外部キーと同じ話。これらは優れた機能ですが、負担になる可能性があります。それらを使用することによる利益が、それらがもたらす制限を上回っているかどうかを真剣に検討する必要があります。

    スキーマ変更の追跡

    スキーマ変更管理は、スキーマ変更の実行だけではありません。また、特に変更を行うのがあなただけではない場合は、スキーマ構造を常に把握している必要があります。

    ClusterControlは、最も一般的なスキーマ設計の問題のいくつかを追跡するためのツールをユーザーに提供します。主キーを持たないテーブルを追跡するのに役立ちます:

    前に説明したように、主キーは直接変更を使用して追加する必要があるため、このようなテーブルを早期にキャッチすることは非常に重要です。

    ClusterControlは、重複するインデックスの追跡にも役立ちます。通常、冗長な複数のインデックスは必要ありません。上記の例では、(k、c)にインデックスがあり、(k)にもインデックスがあることがわかります。列「k」で作成されたインデックスを使用できるクエリは、列(k、c)で作成された複合インデックスも使用できます。冗長なインデックスを保持することが有益な場合もありますが、ケースバイケースでアプローチする必要があります。 MySQL 8.0以降では、インデックスが本当に必要かどうかをすばやくテストできます。次のコマンドを実行して、冗長インデックスを「非表示」にすることができます:

    ALTER TABLE sbtest.sbtest1 ALTER INDEX k_1 INVISIBLE;

    これにより、MySQLはそのインデックスを無視し、監視を通じて、データベースのパフォーマンスに悪影響があったかどうかを確認できます。すべてがしばらくの間(数日または数週間)計画どおりに機能する場合は、冗長なインデックスを削除することを計画できます。何かが正しくないことを検出した場合は、次のコマンドを実行することで、いつでもこのインデックスを再度有効にできます。

    ALTER TABLE sbtest.sbtest1 ALTER INDEX k_1 VISIBLE;

    これらの操作は瞬時に行われ、インデックスは常に存在し、維持されます。オプティマイザーによって考慮されないのはそれだけです。このオプションのおかげで、MySQL8.0でインデックスを削除する方がはるかに安全な操作になります。以前のバージョンでは、誤って削除されたインデックスを再度追加すると、大きなテーブルでは数日ではなくても数時間かかる可能性がありました。

    ClusterControlは、MyISAMテーブルについても通知できます。

    MyISAMにはまだ用途があるかもしれませんが、トランザクションストレージエンジンではないことに注意する必要があります。そのため、レプリケーション設定でノード間にデータの不整合が発生しやすくなります。

    ClusterControlのもう1つの非常に便利な機能は、運用レポートの1つであるスキーマ変更レポートです。

    理想的な世界では、DBAはすべてのスキーマ変更をレビュー、承認、および実装します。残念ながら、これが常に当てはまるとは限りません。このようなレビュープロセスは、アジャイル開発にはうまくいきません。それに加えて、開発者とDBAの比率は通常非常に高く、DBAがボトルネックにならないように苦労するため、これも問題になる可能性があります。そのため、DBAの知識の範囲外でスキーマの変更が実行されるのを見るのは珍しいことではありません。ただし、通常、DBAはデータベースのパフォーマンスと安定性に責任を負います。スキーマ変更レポートのおかげで、スキーマ変更を追跡できるようになりました。

    最初にいくつかの構成が必要です。特定のクラスターの構成ファイル(/etc/cmon.d/cmon_X.cnf)で、どのホストでClusterControlが変更を追跡し、どのスキーマをチェックするかを定義する必要があります。

    schema_change_detection_address=10.0.0.126
    schema_change_detection_databases=sbtest

    それが完了したら、定期的に実行されるレポートをスケジュールできます。出力例は次のようになります。

    ご覧のとおり、前回のレポートの実行以降、2つのテーブルが変更されています。最初の例では、列(k、c)に新しい複合インデックスが作成されています。 2番目の表には、列が追加されています。

    その後の実行で、インデックスや主キーなしで作成された新しいテーブルに関する情報を取得しました。この種の情報を使用すると、必要なときに簡単に行動し、問題が実際にブロッカーになり始める前に問題を解決できます。


    1. MySQLWorkbenchで図からスクリプトを生成する方法

    2. SQL Server-挿入された行のIDを取得する最良の方法は?

    3. 動的SQLの結果はSQLストアドプロシージャの一時テーブルになります

    4. SelectでID列名を指定せずにID列の値を取得する方法-SQLServer/T-SQLチュートリアルパート46