web-dev-qa-db-ja.com

マスターはスレーブを更新しますが、マスター自体は更新しません

アプリケーションがマスターのみを指すセットアップマスター/スレーブがあります。昨日、オレンジ色のフロント表示パネルの「DIMMのマルチビットエラーが検出されました」が原因でマスターがクラッシュしました。

再起動後、マスターが回復に向かったのがわかります。その後、マスターが起動し、アプリケーションはマスターを正常に使用し始めましたが、それでもエラーメッセージがフロント表示パネルに存在します。しかし、テーブルの主キーの制約のために、スレーブが突き出ていました。

私が直面している問題は、マスターのbinlogに存在するものまで、マスターがテーブルデータを持っていることです。しかし、スレーブにはマスターbinlogにないテーブルデータがあります。以下は、マスターテーブルおよびスレーブテーブルと比較した場合のテーブルの詳細です。

Last info in binlog timestamp is 2013-04-29 02:13:11 
System shut down timestamp 2013-04-29 02:54         

            mysql> select * from audit where id=11298907;
            ------------------------------------------------------------
            | id     | ipaddress      | dated        | msisdn  |
            +----------+----------------+-------------------------------
            |11298907 | 82.25.226.183  | 2013-04-29 02:13:11 | 998282821|
            -----------------------------------------------------------
            mysql> select * from audit where id > 11298907 limit 1;

            -----------------------------------------------------------
            | id     | ipaddress      | dated        |msisdn  |
            +----------+----------------+------------------------------
            |11298908 | 82.25.226.183 | 2013-04-29 04:31:13 | 992828111|
            ------------------------------------------------------------

            On Slave
            ==========

            mysql> select * from audit where id=11298907;
            ------------------------------------------------------------
            | id     | ipaddress      | dated        | msisdn  |
            +----------+----------------+-------------------------------
            |11298907 | 82.25.226.183  | 2013-04-29 02:13:11 | 998282821|
            -----------------------------------------------------------



            mysql> select * from audit where id > 11298907 limit 1;

            -----------------------------------------------------------
            | id     | ipaddress      | dated        |msisdn  |
            +--------+----------------+---------------------------------
            |11298908 | 82.25.226.183 | 2013-04-29 02:13:12 | 762616173|
            ------------------------------------------------------------

両方のサーバーはGSTとntp同期されています。また、マスターを再起動した後も同じままです。マスターサーバーを起動するのに約2時間かかりました。マスターが認識していないデータをスレーブだけが持つことができるのはなぜですか?そんなことを誰かに出会わせてください。

1
Mannoj

この理由は非常に簡単です。

innoDBテーブルを使用していて、MySQLサーバーがCOMMITステートメントを処理する場合、トランザクション全体をバイナリログに書き込み、このトランザクションをInnoDBにコミットします。

http://dev.mysql.com/doc/refman/5.5/en/binary-log.html

トラフィックが中程度から少ない期間では、「最後に起こったこと」がバイナリログに記録されてスレーブに渡され、そこで実行されますが、マスターには保持されません。書き込みのたびにバイナリログをディスクに同期するためにsync_binlog = 1を使用しておらず、すべてのInnoDBコミットをディスクにすぐにフラッシュするためにinnodb_flush_log_at_trx_commit = 1を使用していない場合、ACIDに準拠していません。インストール...そしてマシン自体がクラッシュした場合、MySQLにはInnoDBとバイナリログがクラッシュリカバリで一貫していないことを認識する手段がありません。


更新:元の質問は、マスターのbinlogを確認し、スレーブに到達したデータもそこから欠落していることを発見したことを示唆しています。明確にするために、これが当てはまる場合、2つの考えられる説明があります。

  • イベントはマスターバイナリログに「書き込まれ」、スレーブに送信されましたが、ファイルへの「書き込み」とそのファイルをハードドライブにフラッシュするオペレーティングシステムは同じものではありません。 「書き込まれた」データはディスクに永続化されていなくてもOSキャッシュに存在するため、書き込まれたファイルをフラッシュして、フラッシュされていないデータを読み取る必要はありません。

  • 上記のリンクには、binlogがディスクに永続化されたとしても、InnoDBがそれらのトランザクションがコミットされていないことを検出したときに、クラッシュリカバリによってそれらのトランザクションがトリミングされた可能性があることを示唆する言語があります。

クラッシュ後、トランザクションのロールバックを実行した後、MySQLサーバーはロールバックされたInnoDBトランザクションをバイナリログからカットします

この行動の正当性は次のように述べられています:

これにより、バイナリログがInnoDBテーブルの正確なデータを反映し、スレーブがマスターと同期したままになります(ロールバックされたステートメントを受信しません)。

イベントがスレーブに送信される可能性がある時間枠が短いため、このステートメントは完全には当てはまりません。一方、このトリミングが発生した場合、binlogwouldは、マスターに永続化されたデータと一致します。これは、間違いなく、そうでない場合よりも優れています。マスターに永続化されたデータに同意します。

以下のソースコードの例がドキュメントに記載されているプロセスを表しているとは完全には確信していませんが、エラーログに次のようなメッセージがある場合、その説明はあなたの質問に対応しているようです。

sql/binlog.cc:
  sql_print_information("Crashed binlog file %s size is %llu, "
                        "but recovered up to %llu. Binlog trimmed to %llu bytes.",
                        log_name, binlog_size, valid_pos, valid_pos);
3