@RolandoMySQLDBAはこの質問に正確に答えました...しかし、彼はまた、彼の解決策は「迅速かつ汚い」ことを指摘しました。
そして、それは非常に真実の声明です。:)
ここで私に関係するのは、その答えではなく、元の質問が間違った仮定をしているように見えることです。
2つのサーバーにクエリを実行し、どちらがマスターかを尋ねてから、そのサーバーに対するすべてのクエリを実行できます。
問題は、MySQLレプリケーションでは、マスターがマスターであることを真に認識しないことです。
「マスターへの昇格」の概念は、MySQL非同期レプリケーションの概念ではありません。MySQLサーバーをマスターロールに「昇格」することは、MySQLサーバーの「内部」で発生するものとは対照的に、MySQLサーバーの「外部」で発生するものです。
技術的に言えば、バイナリロギングが有効になっているすべてのMySQLサーバーは、スレーブがない場合でもマスターであるため、「マスターへの昇格」はいかなる種類のサーバープロビジョニングによっても行われません。 SHOW MASTER STATUS
スレーブの有無にかかわらず、まったく同じように機能し、まったく同じ結果を返します。2つのスレーブを持つマスターは、1つのスレーブまたは0のスレーブを持つマスターとほぼ同じです。同様に、スレーブがすべてオフラインであるマスターは、マスターと同じです。スレーブがオンラインに戻ると、中断したところから複製を開始するからです。
ある意味では、どちらかのサーバーの唯一の「認識」は、それがマスターであるかどうかではなく、スレーブであるかどうかです。
それが、ローランドのソリューションが求めているものです:「あなたは奴隷ですか?」答えが「いいえ」の場合、仮定はこれがマスターでなければならないということですSTOP SLAVE;
。しかし、停止したスレーブはまだスレーブであるため、「スレーブではない」(いつでも)は「マスターであること」に相当しません。
推定されるマスターで同様のテストを実行できます。
SELECT COUNT(1) FROM information_schema.processlist
WHERE user = 'the_username_used_by_the_slave';
または
SELECT COUNT(1) FROM information_schema.processlist
WHERE command = 'binlog dump';
値がゼロの場合、スレーブのIOスレッドは接続されていません。このテストには同様の欠陥があります。スレーブが管理上切断された場合、隔離された場合、または失敗した場合、スレーブは接続されません。したがって、これでも実際には何も解決されません。
さらに悪いことに(これらのシナリオのいずれかについて)、information_schema.processlist "table"は、選択されるたびにマテリアライズされる仮想テーブルであり、これには時間とコストがかかります。各スレッドのアクティビティはピアインする必要があるため、サーバーが忙しいほどコストがかかります。
より軽量なソリューションは次のとおりです。
SELECT @@global.read_only;
スレーブではread_only
、SUPER
特権のないユーザーが意図せずに書き込むことができないように、グローバル変数を設定する必要があります(また、アプリケーションが持つべきではありませんSUPER
)。スレーブをマスターの役割に手動で「昇格」する場合SET GLOBAL read_only = OFF
、書き込みを有効にします。(これがどのように設定されていても、レプリケーションは常にスレーブに書き込むことができます)。
しかし、これはまだ重要な点を見落としていると思います。
アプリケーションがマスター/スレーブのセットアップでこの決定をヒューリスティックに行うべきではなく、接続ごとではないことを提案します。 アプリケーションはハード構成オプションを使用するか、アプリケーションが気付かないままにして、データベース接続の宛先を別の方法で処理する必要があります。
または、少なくとも、マスターに障害が発生するまでアプリケーションを切り替えないでください。その後、アプリケーションが再び切り替えられることはありません。
私がそう言う理由は次のとおりです。「決定」が行われた場合-誰でも何でも-別のサーバーをマスターにすると、オンラインに戻った後でも、アプリケーションは何らかの理由で元のマスターに戻ることができません、介入なし。
バグを見つけて、ソフトウェアによるクラッシュが発生したとしましょう。mysqld_safe
忠実に再起動しmysqld
、InnoDBクラッシュリカバリは問題なく実行されます。しかし、それには数分かかります。
その間、マスターがダウンしているため、アプリケーションはスレーブに切り替わりました。トランザクションが作成され、注文が行われ、資金が転送され、コメントが投稿され、ブログが編集されました。
これで、元のマスターがオンラインに戻ります。
アプリケーションが元のマスターに戻った場合、絶対に怪我をしていることになります。これは、アプリケーションが平均でスレーブのデータを変更したため、矛盾が発生してレプリケーションが停止する可能性があるためです。時間。一貫性のないデータを持つ2つのデータベースサーバーがあり、手動で調整する必要があります。ドルやポイント、クレジットが関係している場合、残高が一致していません。
したがって、ユーザーの介入なしにアプリケーションが元のマスターに戻ることを許可されないことが重要です。
待って、私が説明したように、このシナリオで問題を見つけましたか? マスターは失敗しましたが、スレーブはマスターではなくスレーブであるとみなされるため、アプリケーションはスレーブを使用しません... information_schema.processlist
マスターサーバーの電源が切れても、スレーブに対するクエリはゼロ以外を返します。
そのため、アプリケーションが何かを発見してもあまり意味がありませんSTOP SLAVE
。そのテストを有効にするには手動で行う必要があるからです。
おそらく、アプリケーションを切り替えられるようにする場合のより良いアプローチは、循環レプリケーションを使用してサーバーを構成することです。
循環レプリケーションには固有の問題がありますが、アプリケーションが常に一度に1つのサーバーにしか書き込むことがない限り、これらの問題のほとんどは問題になりません。言い換えると、両方のマシンはレプリケーションの意味で常に同時にマスターとスレーブの両方ですが、アプリケーションは何らかのメカニズムを介して、一度に1台のマシンのみを「マスター」としてポイントし、書き込む必要があります。 。
MySQLサーバーに分離されているため、HAツールをMySQLサーバーにデプロイすることはできませんが、アプリケーションサーバーで実行されているHAProxyを使用して実装できます。アプリケーションはlocalhostの「MySQL」に接続します。これはMySQLではありませんが、実際にはHAProxy ...であり、TCP接続を適切なMySQLマシンに転送します。
HAProxyは、MySQLサーバーへの接続をテストし、接続を受け入れ認証を許可しているMySQLマシンにのみトラフィックを提供できます。
アプリケーションサーバーで実行されているHAProxyの組み合わせ(リソースに対する要求は、アプリケーションサーバーが行う他のすべてに比べて実質的ではありません。ソケットを結び付けてペイロードを無視するだけです)...およびMySQL循環レプリケーション質問から知られていることに基づいて、おそらくこの場合に私が取るであろうアプローチでしょう。
または、厳密に手動で設定/etc/hosts
する場合は、アプリケーションがMySQLに接続するために使用するホスト名を持つアプリサーバーのファイルのエントリなど、「ディスカバリ」よりもはるかに単純なものを使用します。 masterは、手動プロセスを意図しています。
または、Percona XtraDB Clusterを使用した、より複雑なもの。ただし、PXCに3つのノードがある場合、2つのサーバーは相互に認識できても1つのサーバーから分離されると(3つすべてがまだ実行されている場合)、2つのサーバーは引き続き正常に実行されるため、3番目のサーバーを追加する必要があります1台のサーバーは小さなボールに丸まって、それが奇妙なものであるに違いないと認識しているため、何もすることを拒否します。これは、ネットワークが分割される前にオンラインであったノードの大部分を構成しているのが2つであり、そうでないことを1つが認識するためです。PXCでは、アプリケーションがどのサーバーに接続するかは問題ではありません。
これはすべて、「アプリケーションがサーバーをポーリングしてどちらがマスターであるかを確認しない」と言うことだと言います。遅かれ早かれあなたに噛みつき、噛む日まであなたのパフォーマンスを食いつぶしてしまうからです。