web-dev-qa-db-ja.com

スレーブから逃したトランザクションを取得する

ディザスタリカバリ計画を作成しようとしています。1つのマスター(A)と3つのスレーブ(B、C、D)を使用した一方向レプリケーションがあります。

     A 
    /|\
   / | \
  B  C  D

マスターがクラッシュし、そのサーバー上のすべてのデータが失われ、まだ3つのスレーブがあり、最新のマスターになるように昇格するとします。たとえば、スレーブBが最新で、CとDはそうではありません。私がBを昇格させてスレーブをマスターした時点で、SHOW SLAVE STATUS\Gの結果は次のようになります。

slaveB> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
      Relay_Master_Log_File: master-bin.000002
        Exec_Master_Log_Pos: 1476884

slaveC> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
      Relay_Master_Log_File: master-bin.000002
        Exec_Master_Log_Pos: 78684

slaveD> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
      Relay_Master_Log_File: master-bin.000001
        Exec_Master_Log_Pos: 746848

Bをマスターに昇格させるために、不足しているすべてのトランザクションをCとDに適用したいので、Bが新しいマスターになり、アプリケーションからのクエリの受信を開始する前に、すべてのスレーブが一貫した状態になっています。 BからのバイナリログでCとDからのトランザクションを逃しました(すべてのサーバーで--log-slave-updatesオプションを有効にしました)。

従来の問題の場合、環境はMySQL5.0を使用します

2
altmannmarcelo

変更するために必要なこと、私が呼ぶもの、レプリケーションの参照ポイント。

サーバーB、C、およびDではbinlogが有効になっているため、これは便利です。

あなたが与えた

slaveB> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
      Relay_Master_Log_File: master-bin.000002
        Exec_Master_Log_Pos: 1476884

slaveC> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
      Relay_Master_Log_File: master-bin.000002
        Exec_Master_Log_Pos: 78684

ServerCをServerBのスレーブになるように同期させましょう

ステップ01:ServerCへのすべての書き込みを停止します

STOP SLAVE;

ステップ02:ServerCで、SHOW MASTER STATUS;を実行します

出力がmaster-bin.000003位置12345678だったとしましょう

ステップ03:ServerCで、実行

mysqlbinlog master-bin.000003 > latest-binlog.sql

ステップ04:STEP 03から位置を特定し、前後に3行を表示します

grep -C 3 12345678 latest-binlog.sql

タイムスタンプが「2013-09-0301:23:45」だったとしましょう

ステップ05:ServerBのバイナリログでその位置のタイムスタンプを検索します

ServerBのバイナリログがmaster-bin.000004であるとしましょう

ステップ06:ServerBのバイナリログマスター内のタイムスタンプに一致するダンプ位置-bin.000004

SQLFILE=dumpstuff.sql
BINLOG="master-bin.000004"
DT2="2013-09-03 01:23:45"
DT1="2013-09-03 01:00:00"
mysqlbinlog --start-datetime="${DT1}" --stop-datetime="${DT2}" > ${SQLFILE}

ステップ07:SQLFILE内のタイムスタンプを見つけ、位置を見つけます

位置が87654321だとしましょう

ステップ08:SlaveCをSlaveBに接続します

SlaveCで、これを実行します

STOP SLAVE;
CHANGE MASTER TO master_log_file='master-bin.000004',master_log_pos=87654321;
START SLAVE;

それだけです!!!

警告#1

これらすべての同じ手順を繰り返して、ServerDをServerBに同期します

警告#2

これらの手順を実行してもデータが信頼できない場合は、Percona Toolsをダウンロードし、 pt-table-checksum を使用して各スレーブを新しいマスターと照合してください。違いがある場合は、 pt-table-sync を実行してSQLを生成し、違いを修復できます。

更新2013-09-0512:28 EDT

あなたはこのコメントをしました

ステップ2、3、4では、マスターbinlogにアクセスできません。slaveCで最新の適用済みトランザクションを取得する方法は、slaveCリレーログから(show slave statusのRelay_Master_Log_FileとExec_Master_Log_Posを使用して)抽出することだと思います。私は正しいですか?手順5から8は正しいようです。

mysqlbinlog をリモートで使用できます -read-from-リモートサーバー 。その上、あなたは古いマスター、ServerAに戻らない。あなたはスレーブ間でこれらのことを行っており、ServerBを新しいマスターにしています。管理されたホスティング会社を使用している場合は、それらの管理者がこのプロセスに関与する必要があります。少なくとも、Linuxボックスと必要なすべてのフォルダーのアクセス許可にアクセスできるようにするためのSSHトンネルアクセスを提供できます。 MySQL認証は必要ありません。

3
RolandoMySQLDBA

データフォルダ同期(rsync)ではなくバイナリログから検索する必要がある理由があるかどうかを教えてください。アプリケーションがBへの書き込みを開始していないので、MySQLサーバーを停止してクリーンなrsyncを実行する余裕があると思います(データが大きすぎるのではないでしょうか?)。私はこの方法を直接体験しましたが、それは魅力のように機能しました。 binlogを読み取る(位置を数える際の人間の介入を読み取る)と、間違った位置になってしまう可能性があり、最悪の場合、重複したエントリを処理することになります。

0
kd85