web-dev-qa-db-ja.com

MySQLマスタースレーブでマスターを決定する方法

私はMySQLマスタースレーブレプリケーションを設定しており、スレーブがマスターに昇格する(マスターがダウンした場合)フェイルオーバー状況を処理する方法を理解しようとしています。

アプリケーションサーバーはすべての書き込みを現在のマスターに送信する必要がありますが、2つのdbサーバーが物理的に異なる場所にあるまったく異なるサブネット上にあるため、マスターとスレーブ(ハートビート、keepalived)間でサーバーレベルのHAを使用できません。

これは、アプリケーションレベルで処理する必要があることだと思います。 2つのサーバーにクエリを実行して、どちらがマスターであるかを尋ね、そのサーバーに対するすべてのクエリを実行できます。

MySQLに現在のサーバーがマスター/スレーブレプリカのマスターであるかどうかを確認するクエリはありますか?

18
Ethan Hayon

@RolandoMySQLDBAは質問に正確に答えました...しかし、彼の解決策は「迅速かつ汚い」ものであると彼は指摘しました。

そしてそれは非常に本当の声明です。 :)

ここで私が関係するのはその答えではなく、元の質問が誤った仮定をしているように見えることです。

2つのサーバーにクエリを実行して、どちらがマスターであるかを尋ね、そのサーバーに対するすべてのクエリを実行できます。

問題は、MySQLレプリケーションでは、マスターがマスターであることをマスターが認識していないことです。

「マスターへの昇格」の概念は、MySQL非同期レプリケーションの概念ではありません。 MySQLサーバーをマスターの役割に「昇格」することは、MySQLサーバーの「内部」で発生するものとは対照的に、「外部」のMySQLサーバーで発生するものです。

「マスターへの昇格」は、いかなる種類のサーバープロビジョニングでも行われません。これは、技術的に言えば、バイナリロギングが有効になっているすべてのMySQLサーバーが、スレーブがない場合でもマスターになるためです。 SHOW MASTER STATUSはまったく同じように動作し、スレーブかどうかにかかわらずまったく同じ結果を返します。スレーブが2つのマスターは、スレーブが1つまたは0のマスターとほぼ同じです。同様に、スレーブがすべてオフラインになっているマスターも、マスターと同じです。スレーブがオンラインに戻ったときに、中断したところから複製を取得するためです。

ある意味で、どちらかのサーバー側の唯一の「認識」は、それがマスターであるかどうかではなく、スレーブである(または「ない」)かどうかです。

それが、Rolandoのソリューションが要求するものです:「あなたは奴隷ですか?」答えが「いいえ」の場合、仮定はこれがマスターでなければならないということです... 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_safemysqldを忠実に再起動し、InnoDBのクラッシュリカバリは問題なく実行されます。しかし、それは数分かかります。

その間、マスターがダウンしているため、アプリケーションがスレーブに切り替わりました。トランザクションが作成され、注文が行われ、送金され、コメントが投稿され、ブログが編集されました。

これで、元のマスターがオンラインに戻りました。

アプリケーションが元のマスターに戻った場合、あなたは絶対に傷ついた世界にいます。それは、アプリケーションがスレーブ上のデータを変更したため、矛盾が原因でレプリケーションが停止するためです。時間。これで、手動で調整する必要がある矛盾したデータを持つ2つのデータベースサーバーができました。ドル、ポイント、またはクレジットが関係している場合は、残高が一致していません。

したがって、アプリケーションが介入なしに元のマスターに戻ることができないようにすることが重要です。

待って、私が説明したように、このシナリオの問題を見つけましたか?マスターは失敗しましたが、スレーブはまだスレーブであり、スレーブではないと考えているため、アプリケーションはスレーブを使用していません。マスター...スレーブのinformation_schema.processlistクエリは、マスターサーバーの電源が切断されている場合でもゼロ以外を返します。

そのため、そのテストを有効にするには手動でSTOP SLAVEを実行する必要があるため、アプリケーションが何かを検出してもあまり意味がありません。

アプリケーションを切り替えられるようにする場合は、循環複製を使用してサーバーを構成することをお勧めします。

循環レプリケーションにはそれ自体に固有の問題がありますが、アプリケーションが常に一度に1つのサーバーに書き込むだけである限り、これらの問題のほとんどは問題ではなくなります。言い換えると、レプリケーションの意味では、両方のマシンが常に同時にマスターとスレーブの両方になりますが、アプリケーションは、何らかのメカニズムを介して、書き込み可能な「マスター」として常に一度に1つのマシンのみを指します。 。

MySQLサーバーにHAツールを配置することはできないため、HAサーバーをMySQLサーバーにデプロイすることはできませんが、アプリケーションサーバーでHAProxyを実行して実装することはできます。アプリケーションはlocalhost上の「MySQL」に接続します。これはMySQLとはまったく異なりますが、実際にはHAProxy ...であり、TCP接続を適切なMySQLマシンに転送します。

HAProxyはMySQLサーバーへの接続をテストし、接続を受け入れて認証を許可しているMySQLマシンへのトラフィックのみを提供できます。

アプリケーションサーバーで実行されているHAProxyの組み合わせ(リソースの需要は、アプリケーションサーバーが実行する必要がある他のすべてと比較すると、それほど大きくありません-ソケットを結合してペイロードを無視するだけです)...およびMySQL循環レプリケーション質問からわかったことに基づいて、私がおそらくこの例でとるアプローチでしょう。

または、厳密に手動のセットアップの場合は、アプリケーションサーバーがMySQLへの接続に使用するホスト名を含むアプリケーションサーバーの/etc/hostsファイルのエントリなど、「検出」よりもはるかに簡単なものを使用して、手動で更新できます-スレーブからマスターへの昇格は手動プロセスであると想定しています。

または、Percona XtraDB Clusterを使用した、より複雑なもの。ただし、この場合、PXCに3つのノードがあるため、2つのサーバーがお互いを認識できるが、1つのサーバーから分離される場合(3つすべてがまだ実行されている場合)、2つのサーバーは問題なく稼働し続けますが、3番目のサーバーを追加する必要があります。 1サーバーは小さなボールに丸まり、奇妙なものである必要があることを認識しているため、何もすることを拒否します。これは、ネットワークが分割される前にオンラインであったノードの過半数を構成していることを2が認識し、1がオンラインではないことを認識しているために機能します。 PXCでは、アプリケーションがどのサーバーに接続するかは重要ではありません。

これはすべて、「アプリケーションがサーバーをポーリングして、どちらがマスターであるかを確認しないでください」と言うことです。それは遅かれ早かれあなたを噛み、噛むその日まであなたのパフォーマンスをかじってしまうからです。

15

マスター/スレーブのみを使用している場合は、以下に簡単な方法を示します。

SELECT COUNT(1) SlaveThreadCount
FROM information_schema.processlist
WHERE user='system user';

これは何を教えてくれますか?

  • SlaveThreadCount = 0の場合、マスターを持っています
  • SlaveThreadCount> 0の場合、スレーブがあります

[〜#〜]警告[〜#〜]:これは、STOP SLAVE;を実行しない限り機能します

もう1つ試すことはこれです。スレーブでバイナリログを無効にしてSHOW MASTER STATUS;を実行すると、マスターから現在のバイナリログが提供されます。奴隷はあなたに何も与えません。

10
RolandoMySQLDBA

mysqlプロンプトからこのステートメントを実行する
mysql>スレーブステータスを表示します。

スレーブでは多くのパラメータとその値/ステータスが表示されますが、マスターではEmpty setが表示されます

0
akrai48