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

MySQLとMariaDBで安全な方法でスキーマ変更を実行する方法

    本番データベースでスキーマの変更を実行する前に、確実なロールバック計画があることを確認する必要があります。また、変更手順が別の環境で正常にテストおよび検証されていること。同時に、変更によってビジネスに許容できる影響がまったくないか、最小限に抑えられるようにするのはあなたの責任です。確かに簡単な作業ではありません。

    この記事では、MySQLとMariaDBでデータベースの変更を制御された方法で実行する方法を見ていきます。私たちはあなたの日々のDBAの仕事におけるいくつかの良い習慣について話します。実際の操作中の前提条件とタスク、およびデータベーススキーマの変更に対処するときに直面する可能性のある問題に焦点を当てます。また、プロセスに役立つ可能性のあるオープンソースツールについても説明します。

    テストとロールバックのシナリオ

    バックアップ

    データを失う方法はたくさんあります。スキーマのアップグレードの失敗はその1つです。アプリケーションコードとは異なり、ファイルのバンドルを削除して、新しいバージョンが正常にデプロイされたことを宣言することはできません。また、変更をロールバックするために古いファイルのセットを元に戻すこともできません。もちろん、別のSQLスクリプトを実行してデータベースを再度変更することもできますが、変更をロールバックする唯一の正確な方法は、データベース全体をバックアップから復元することです。

    ただし、データベースを最新のバックアップにロールバックする余裕がない場合、またはメンテナンスウィンドウが十分に大きくないため(システムパフォーマンスを考慮)、変更前にデータベースの完全バックアップを実行できない場合はどうなりますか?

    洗練された冗長な環境があるかもしれませんが、プライマリとスタンバイの両方の場所でデータが変更されている限り、それについて行うことはあまりありません。多くのスクリプトは一度だけ実行できます。または、変更を元に戻すことはできません。 SQL変更コードのほとんどは2つのグループに分類されます:

    • 1回実行–同じ列をテーブルに2回追加することはできません。
    • 元に戻すことはできません–その列を削除すると、その列はなくなります。間違いなくデータベースを復元することはできますが、それは正確には元に戻すことではありません。

    この問題には、少なくとも2つの方法で取り組むことができます。 1つは、バイナリログを有効にして、PITRと互換性のあるバックアップを取ることです。このようなバックアップは、完全で、完全で、一貫している必要があります。エクストラバックアップの場合、完全なデータセットが含まれている限り、PITRと互換性があります。 mysqldumpの場合、PITR互換にするオプションもあります。小さな変更の場合、mysqldumpバックアップのバリエーションは、変更するデータのサブセットのみを取得することです。これは--whereオプションで実行できます。バックアップは計画されたメンテナンスの一部である必要があります。

    mysqldump -u -p --lock-all-tables --where="WHERE employee_id=100" mydb employees> backup_table_tmp_change_07132018.sql

    もう1つの可能性は、CREATE TABLEASSELECTを使用することです。

    データまたは単純な構造変更を固定一時テーブルの形式で保存できます。このアプローチでは、変更をロールバックする必要がある場合にソースを取得します。多くのデータを変更しない場合は、非常に便利な場合があります。ロールバックは、そこからデータを取り出すことで実行できます。データをテーブルにコピーしているときにエラーが発生した場合、データは自動的に削除されて作成されないため、ステートメントで必要なコピーが作成されていることを確認してください。

    もちろん、いくつかの制限もあります。

    基になるSELECTステートメントの行の順序は常に決定できるとは限らないため、CREATE TABLE ...IGNORESELECTおよびCREATETABLE... REPLACE SELECTは、ステートメントベースのレプリケーションに対して安全ではないというフラグが立てられます。このようなステートメントは、ステートメントベースモードを使用するとエラーログに警告を生成し、MIXEDモードを使用すると行ベースの形式を使用してバイナリログに書き込まれます。

    このような方法の非常に簡単な例は次のとおりです。

    CREATE TABLE tmp_employees_change_07132018 AS SELECT * FROM employees where employee_id=100;
    UPDATE employees SET salary=120000 WHERE employee_id=100;
    COMMMIT;

    もう1つの興味深いオプションは、MariaDBフラッシュバックデータベースです。間違った更新または削除が発生し、特定の時点でデータベース(またはテーブルのみ)の状態に戻したい場合は、フラッシュバック機能を使用できます。

    ポイントインタイムロールバックを使用すると、DBAは、バックアップからの復元を実行するのではなく、トランザクションを前の時点にロールバックすることで、データをより迅速に回復できます。 ROWベースのDMLイベントに基づいて、フラッシュバックはバイナリログを変換して目的を逆にすることができます。つまり、特定の行の変更をすばやく元に戻すのに役立ちます。たとえば、DELETEイベントをINSERTに、またはその逆に変更でき、UPDATEイベントのWHERE部分とSET部分を交換します。この単純なアイデアは、特定の種類のミスや災害からの回復を劇的にスピードアップすることができます。 Oracleデータベースに精通している人にとって、これはよく知られている機能です。 MariaDBフラッシュバックの制限は、DDLサポートがないことです。

    遅延レプリケーションスレーブを作成する

    バージョン5.6以降、MySQLは遅延レプリケーションをサポートしています。スレーブサーバーは、少なくとも指定された時間だけマスターより遅れることがあります。デフォルトの遅延は0秒です。 CHANGE MASTER TOのMASTER_DELAYオプションを使用して、遅延をN秒に設定します。

    CHANGE MASTER TO MASTER_DELAY = N;

    適切な復旧シナリオを準備する時間がなかった場合は、これは良いオプションです。問題のある変化に気付くには、十分な遅延が必要です。このアプローチの利点は、変更を修正するために必要なデータを取り出すためにデータベースを復元する必要がないことです。スタンバイDBが稼働しており、必要な時間を最小限に抑えるデータを取得する準備ができています。

    クラスターの一部ではない非同期スレーブを作成する

    ガレラクラスターに関しては、変更のテストは簡単ではありません。すべてのノードが同じデータを実行し、高負荷はフロー制御に悪影響を与える可能性があります。したがって、変更が正常に適用されたかどうかだけでなく、クラスターの状態への影響も確認する必要があります。テスト手順を本番ワークロードにできるだけ近づけるために、非同期スレーブをクラスターに追加して、そこでテストを実行することをお勧めします。技術的にはクラスターの一部ではないため、テストはクラスターノード間の同期に影響を与えませんが、実際のデータでテストを確認するオプションがあります。このようなスレーブは、ClusterControlから簡単に追加できます。

    ClusterControlは非同期スレーブを追加します

    上のスクリーンショットに示されているように、ClusterControlは、いくつかの方法で非同期スレーブを追加するプロセスを自動化できます。ノードをクラスターに追加し、スレーブを遅延させることができます。マスターへの影響を減らすために、スレーブを構築するときにデータソースとしてマスターの代わりに既存のバックアップを使用できます。

    データベースのクローン化と時間の測定

    適切なテストは、生産の変更に可能な限り近づける必要があります。これを行う最良の方法は、既存の環境のクローンを作成することです。

    テスト用のClusterControlクローンクラスター

    レプリケーションを介して変更を実行する

    変更をより適切に制御するために、事前にスレーブサーバーに変更を適用してから、切り替えを行うことができます。ステートメントベースのレプリケーションの場合、これは正常に機能しますが、行ベースのレプリケーションの場合、これはある程度まで機能する可能性があります。行ベースのレプリケーションでは、テーブルの最後に追加の列を存在させることができるため、最初の列を書き込むことができる限り、問題はありません。最初にこれらの設定をすべてのスレーブに適用し、次にスレーブの1つにフェイルオーバーしてから、マスターに変更を実装し、それをスレーブとして接続します。変更にテーブルの中央の列の挿入または削除が含まれる場合、行ベースのレプリケーションで機能します。

    操作

    メンテナンス期間中は、データベースにアプリケーショントラフィックを配置したくありません。会社全体に分散しているすべてのアプリケーションをシャットダウンするのが難しい場合があります。または、特定のホストのみがリモートからMySQLにアクセスできるようにします(監視システムやバックアップサーバーなど)。この目的のために、Linuxパケットフィルタリングを使用できます。使用可能なパケットフィルタリングルールを確認するには、次のコマンドを実行します。

    iptables -L INPUT -v

    使用するすべてのインターフェースでMySQLポートを閉じるには:

    iptables -A INPUT -p tcp --dport mysql -j DROP

    メンテナンスウィンドウの後でMySQLポートを再度開くには:

    iptables -D INPUT -p tcp --dport mysql -j DROP

    ルートアクセスがない場合は、max_connectionを1または「スキップネットワーキング」に変更できます。

    ロギング

    ロギングプロセスを開始するには、次のようにMySQLクライアントプロンプトでteeコマンドを使用します。

    mysql> tee /tmp/my.out;

    このコマンドは、現在のMySQLログインセッションの入力と出力の両方を/tmp/my.outという名前のファイルに記録するようにMySQLに指示します。次に、sourceコマンドを使用してスクリプトファイルを実行します。

    実行時間をより正確に把握するために、プロファイラー機能と組み合わせることができます。プロファイラーを開始する

    SET profiling = 1;

    次に、

    を使用してクエリを実行します
    SHOW PROFILES;

    プロファイラーが統計を持っているクエリのリストが表示されます。最後に、調査するクエリを選択します

    SHOW PROFILE FOR QUERY 1;

    スキーマ移行ツール

    多くの場合、マスターで直接ALTERを実行することはできません。ほとんどの場合、スレーブで遅延が発生し、これはアプリケーションに受け入れられない可能性があります。ただし、実行できるのは、ローリングモードで変更を実行することです。スレーブから始めて、変更がスレーブに適用されたら、スレーブの1つを新しいマスターとして移行し、古いマスターをスレーブに降格して、変更を実行します。

    このようなタスクに役立つ可能性のあるツールは、Perconaのpt-online-schema-changeです。 Pt-online-schema-changeは簡単です。目的の新しいスキーマを使用して一時テーブルを作成します(たとえば、インデックスを追加したり、テーブルから列を削除したりした場合)。次に、古いテーブルにトリガーを作成します。これらのトリガーは、元のテーブルで発生した変更を新しいテーブルにミラーリングするためにあります。変更は、スキーマ変更プロセス中にミラーリングされます。元のテーブルに行が追加されると、その行も新しいテーブルに追加されます。 MySQLが内部でテーブルを変更する方法をエミュレートしますが、変更したいテーブルのコピーで機能します。これは、元のテーブルがロックされておらず、クライアントがそのテーブル内のデータの読み取りと変更を続行できることを意味します。

    同様に、古いテーブルで行が変更または削除された場合、その行は新しいテーブルにも適用されます。次に、古いテーブルと新しいテーブルの間で(LOW_PRIORITY INSERTを使用して)データをコピーするバックグラウンドプロセスが開始されます。データがコピーされると、RENAMETABLEが実行されます。

    もう1つの興味深いツールはgh-ostです。 Gh-ostは、pt-online-schema-changeと同様に、変更されたスキーマを使用して一時テーブルを作成します。次のパターンを使用して古いテーブルから新しいテーブルにデータをコピーするINSERTクエリを実行します。それにもかかわらず、トリガーは使用しません。残念ながら、トリガーは多くの制限の原因となる可能性があります。 gh-ostは、バイナリログストリームを使用してテーブルの変更をキャプチャし、それらをゴーストテーブルに非同期的に適用します。 gh-ostがスキーマ変更を正しく実行できることを確認したら、実際に実行します。移行のテストプロセス中にgh-ostによって作成された古いテーブルを手動で削除する必要がある場合があることに注意してください。 --initially-drop-ghost-tableフラグと--initially-drop-old-tableフラグを使用して、gh-ostにそれを実行するように依頼することもできます。実行する最後のコマンドは、変更をテストするために使用したものとまったく同じで、-executeを追加しただけです。

    pt-online-schema-changeとgh-ostは、Galeraユーザーの間で非常に人気があります。それでも、Galeraにはいくつかの追加オプションがあります。TotalOrderIsolation(TOI)とRolling Schema Upgrade(RSU)の2つの方法には、長所と短所の両方があります。

    TOI-これはデフォルトのDDLレプリケーション方法です。書き込みセットを作成するノードは、解析時にDDLを検出し、DDL処理を開始する前に、SQLステートメントのレプリケーションイベントを送信します。スキーマのアップグレードは、すべてのクラスターノードで同じ全順序シーケンスで実行され、操作中に他のトランザクションがコミットされないようにします。この方法は、オンラインスキーマのアップグレードをクラスター全体に複製し、テーブル全体をロックしてもかまわない場合に適しています(MySQLでデフォルトのスキーマ変更が発生した場合と同様)。

    SET GLOBAL wsrep_OSU_method='TOI';

    RSU-スキーマのアップグレードをローカルで実行します。この方法では、書き込みはそれらが実行されているノードにのみ影響します。変更はクラスターの残りの部分には複製されません。この方法は、競合しない操作に適しており、クラスターの速度を低下させることはありません。

    SET GLOBAL wsrep_OSU_method='RSU';

    ノードがスキーマのアップグレードを処理している間、ノードはクラスターと非同期になります。スキーマアップグレードの処理が完了すると、遅延レプリケーションイベントが適用され、クラスターと同期されます。これは、大量のインデックスを作成するのに適したオプションです。

    結論

    ここでは、スキーマ変更の計画に役立つ可能性のあるいくつかの異なる方法を紹介しました。もちろん、それはすべてアプリケーションとビジネス要件によって異なります。変更計画を設計し、必要なテストを実行することはできますが、問題が発生する可能性はわずかです。マーフィーの法則によると、「チャンスを与えれば、どのような状況でも事態はうまくいかないでしょう」。したがって、これらの変更を実行するさまざまな方法を試して、最も快適な方法を選択してください。


    1. SQL Server2014CTP1用の新しいVMを準備します

    2. ビジネス継続性のためのPostgreSQLの構成

    3. ウィンドウ関数でリングデータ構造を使用する方法

    4. T-SQLとSQL