Mysqlマスターのbinlogファイルを継続的に監視し、破損していないかどうかを検出するための優れた方法があるかどうか疑問に思いました。
Binlogが破損していないかどうかを確認するために探すべき4つのことがあります。
2011年12月26日に、MySQLのバージョンや binlog形式に関係なく (16進値0xfe 0x62 0x69 0x6e
)のbinlogの先頭にある ベースの64の数値について書きました ( STATEMENT、ROW、MIXED)。この16進値がbinlogのヘッダーにない場合は、間違いなく破損しています。
Binlogの位置には、対応するファイルサイズがあります。つまり、mysqldがSQLコマンドを記録するたびに、次のことを実行します。
これに照らして、SHOW MASTER STATUS;
を実行し、次のようなものを取得できます。
mysql> show master status;
+------------------+-----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+-----------+--------------+------------------+
| mysql-bin.000109 | 569025336 | | |
+------------------+-----------+--------------+------------------+
1 row in set (0.00 sec)
mysql>
書き込みが行われていない場合(低書き込み、高読み取り)、binlogのファイルサイズを報告されたbinlogの位置と比較できます。
両方の値を取得して比較します。
Binlogが/ var/lib/mysqlにある場合
BINLOG_INFO=/tmp/binlog.txt
mysql -u... -p... -ANe"show master status" > ${BINLOG_INFO}
BINLOG_FIL=`cat ${BINLOG_INFO} | awk '{print $1}'`
BINLOG_POS=`cat ${BINLOG_INFO} | awk '{print $2}'`
cd /var/lib/mysql
BINLOG_SIZ=`ls -l ${BINLOG_FIL} | awk '{print $5}'`
書き込みが行われていない場合、BINLOG_SIZ
はBINLOG_POS
と等しくなければなりません
書き込みが行われている場合、BINLOG_SIZ
はBINLOG_POS
以上である必要があります
BINLOG_SIZ
がBINLOG_POS
より大きくなることはありません。その場合、binlogは破損している必要があります。
mysqlbinlog ユーティリティは、binlogのテキスト表現をダンプします。出力のいずれかが文字化けしている場合は、破損しています。ただし、次のような場合は、結論にジャンプしないでください。
BINLOG ' WFxKTRNJAAAAPwAAAKY/YwAAABsAAAAAAAEACHdlYmVkaTMwAA1QYXJ0bmVyQ29uZmlnAAQICA8P BC0AYwAA WFxKTRhJAAAAXAAAAAJAYwAAABsAAAAAAAEABP // 8BoSAAAAAAAAggMAAAAAAAAJUEFDS0NPVU5U Azc3MfAaEgAAAAAAAIIDAAAAAAAACVBBQ0tDT1VOVAM3NzI = '/* * /;!
これは、実際にはmysqlbinlog出力の先頭にある通常の署名です。私はこれについて2011年2月4日に書き戻しました: MySQLマスターbinlogの破損 。これが唯一の例外です。このように見えないmysqlbinlogからの文字化けした出力は、binlogの破損の明確な兆候です。
複製のしくみから、これは両刃の剣です。それでもなお、2つの側面で役立つ可能性があります。リレーログには、バイナリログとまったく同じ特性があることに注意してください。
スレーブでは、IOスレッドは、マスターからの着信binlogエントリを解析し、それらをスレーブの現在のリレーログに記録します。実際には、 mysqlbinlog のようなプロセスを実行しています。 IOスレッドで使用されるメカニズムは単純です:
ステップ3が失敗した場合、これはIOスレッドが次の着信SQLで解析できなかったことを意味します。
スレーブは、エラーログに次のように書き込むことで、この失敗を明らかにします。
[ERROR] Error reading packet from server: Client requested master to start replication from impossible position ( server_errno=1236).
[ERROR] Slave I/O: Got fatal error 1236 from master when reading data from binary log: 'Client requested master to start replication from impossible position', Error_code: 1236
111014 20:25:48 [Note] Slave I/O thread exiting, read up to log 'mysql-bin.001067', position 183468345.
エラー番号1236が登録済みのエラー状態であるという事実は、このimpossible position
シナリオが、着信SQLの正常な読み取りに失敗した場合に発生する可能性があることを示しています。私は2011年10月20日にこれについて書きました: ディスクスペースの停止があったときにMy SQLDBマスターからマスターへのレプリケーションを処理する方法
スレーブは、着信SQLを予期する前に、読み取ったヘッダー(Binlogコメント)から必要な位置を認識しています。これには2つの原因があります。
ネットワーク伝送ノイズまたはパケットのドロップがあった場合、そのわずかな「げっぷ」がSQLステートメントの読み取りを中断します。したがって、後続のSQLではなく、ヘッダーコメントが書き込まれる可能性があります。
マスターのbinlogが最初から破損している場合、スレーブのIOスレッドは、より明白な理由で失敗します:GARBAGE IN、GARBAGE OUT !!!
エラーメッセージの例には、Slave I/O thread exiting, read up to log 'mysql-bin.001067', position 183468345.
と記載されています。これが、どの原因が発生したかを知る方法です。スレーブで以下を実行します。
STOP SLAVE;
CHANGE MASTER TO
MASTER_LOG_FILE=''mysql-bin.001067'',
MASTER_LOG_POS=183468345;
START SLAVE;
SELECT SLEEP(10);
SHOW SLAVE STATUS\G
SHOW SLAVE STATUS\G
を実行すると、
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
レプリケーションは問題ありません。 CAUSE #1
でした
しかし、あなたが見るなら
Slave_IO_Running: No
Slave_SQL_Running: Yes
[〜#〜] bang [〜#〜]!!! ...とにかくマスターbinlogが壊れていました(CAUSE #2
)
マスターをmysqldumpし、スレーブにロードして、レプリケーションを最初からセットアップする必要があります。
言うまでもなく、binlogは通常破損しません。これが繰り返し発生する問題である場合は、システムの安定性に根本的な問題がある可能性があります。
ログをオフサイトアーカイブに送信した後、ログを検証するために使用するスニペットは次のとおりです。
dev@server:~$ mysqlbinlog --verbose --base64-output=decode-rows mysql-bin.000004 | tail -n 5 | head -n 1
期待される応答:
#121120 23:41:44 server id 81 end_log_pos 4225079 Rotate to mysql-bin.000005 pos: 4
size of the log under test ^^^^^^^ next log ^^^^^^^^^^^^^^^^
出力がこのパターンに一致し、表示されるサイズが正しく、次のログの名前が正しい場合、これはログが無傷であることの妥当な確認です。
もちろん、このテストは、サーバーが書き込みを終了したログファイルに対してのみ有効です...まだ開いているログには、最後にローテーションイベントがありません。