[前][次][番号順一覧][スレッド一覧]

mysql:11407

From: zen kishimoto <zen kishimoto <zen@xxxxxxxxxx>>
Date: Thu, 12 May 2005 10:32:12 -0700
Subject: [mysql 11407] データリカバリー

データリカバリー
Russell Dyer著
http://dev.mysql.com/tech-resources/articles/point_in_time_recovery.html

mysqldumpの様なユーティリティはMySQLのデータやテーブル・スキーマ
をバックアップするのに有益です。バックアップは通常一日
一回または決められた間隔で行われます。しかし、もしデータが最後の
バックアップの後、数時間後に紛失した場合、そのデータは
回復できないかも知れません。連続してデータを守る幾つか
の方法があります。中途のデータを回復するのに使う
ことが出来る方法1つはバイナリー・ログを使用することです。
バイナリー・ログはサーバーが実行する際に全てのSQLの
トランザクションを記録します。管理者の中には
サーバーの性能が落ちることを心配してロギングを最少化しようとする
人がいます。平均するとバイナリー・ログをオンにしてもサーバーは
1%程度しか性能が落ちません。これがあれば1分刻みで
データの回復ができます。

バイナリーログの設定

バイナリーログはサーバーで実際に実行されたか試みられた
SQLトランザクション全てをバイナリー・ファイルに記録
されます。 mysqlbinlogユーティリティを使えばバイナリーログ
ファイルの内容を抽出し、SQL ステートメントを再び
容易に実行できます。バイナリー・ロギングをオンにするため
には以下の1行を[mysqld]グループのサーバー・オプションファイルに追加して
ください。
(例えば /etc/my.cnf または c:\my.iniこれはシステムに依存します。)

log-bin = /var/log/mysql/bin.log

どのパスを使うかは使用しているファイル・システムや設定
によります。ログが格納されるディレクトリを生成して、ディレクトリ
の所有者と許可を設定する必要があります。データを
バックアップするパスとログファイルのパスは違うハード
ドライブにしておくのをお勧めします。 上記のファイル名
の接尾辞ログは自動的に6桁の番号に置き換えられます。バイナリー
ログは特定のデータベースに限定できますし、ログから特定の
データベースを削除できます。詳細なログのチューニング に
関してはバイナリーログのドキュメントを参照してください。
オプション・ファイルに上記の追加をしてから、この変化
を反映させるためにMySQLサーバーを再スタートする
必要があります。

mysqldumpのようなものを使って正常なバックアップを
する他、バックアップでバイナリー・ログの始めを
指定したいと思うかもしれません。これはバックアップ
を実行する時ログをフラッシュすることで出来ます。以下
のcronのような一行か似たようなすケージュールの
ユーティリティを使用します。

mysqladmin -u root -pmypwd flush-logs

この行では、mysqladminユーティリティはサーバーのログを
フラッシュするのに使用されます。mysqlのクライアント
からFLUSH LOGSステートメントを実行することでも
同じことができます。

簡単な暫定的回復

毎日のバックアップとバイナリーログを実行すし、MySQLのサーバー
からデータを回復するのはめんどくさいプロシージャではありますが
簡単なことです。例として毎日午前零時にmysqldumpを使用して
データをバックアップしているとしましょう。更に、ある日
(例えば2005年の4月20日の午前10時に)データが紛失された
としましょう。回復するためにはまづMySQLのサーバーを停止
し、再スタートする際他のユーザにアクセスを禁じてください。
それにはこうします。

mysqld --socket=/tmp/mysql_restore.sock --skip-networking

--socketオプションはUnixシステムの異なった
ソケットファイルを一時的に指定するものです。Windows では
パスやファイル名なしで、ネームド・パイプ(例えばMySQL_restore)を
使用します。

mysqld-nt --enable-named-pipe \
--socket=MySQL_restore --skip-networking

NTベースでないWindows ではネームド・パイプは適用できませんので
TCP/IPを使用してください。この場合--portオプションを使って
3306以外のポート番号でサーバーをスタートさせてください。プリビレッジ
がない使用されていないどのポートを使用しても構いません。

--skip-networking オプションはTCP/IPでユーザが
サーバーやソケット・ファイルやネームド・パイプにアクセスできない
ようにします。localhostからの接続のみを許可します。これで
あってもサーバーに接続しているコンソールからアクセスは
できます。またはセキュアー・シェルからの接続も可能です。
異なったソケット名を使ったオプションはオーサライズされない
ユーザやサーバ上のAPIのスクリプトがデータが回復されるまで
データベースにアクセスできなくなります。

サーバーを完全に掌握したら、データを回復している最中
に他のユーザがサーバーにアクセスするという問題を考慮せず
作業できます。最初は以下のように昨夜のバックアップ
からのダンプ・ファイルを回復します。

mysql -u root -pmypwd --socket=/tmp/mysql_restore.sock \
< /var/backup/20050420.sql

実際のパスやファイルの名前はサーバー毎に異なります。以下は
昨夜の段階でのデータを回復します。これはその日の最初での
ものではありません。ダンプ・ファイルが生成されてから、
トランザクションを回復するには mysqlbinlogユーティリティ
を使用します。毎夜バックアップし、毎日ログを
フラッシュするのであれば以下のようにしてバイナリーログ
を回復できます。

mysqlbinlog /var/log/mysql/bin.123456 \
| mysql -u root -pmypwd \
--socket=/tmp/mysql_restore.sock

この例ではmysqlbinlogの結果はパイプされてmysqlのクライアント
に渡されて処理されます。これが終了するとテンポラリー
ソケットファイルとネットワークの制限なしでMysQLサーバー
を再スタートします。

このステップで最終のバックアップの時点データを回復します。
それから最後にログがフラッシュされてから実行された全てのSQL
ステートメントを再度実行します。最後のバイナリー・ログ
ファイルの名前を回復するにはログを含むディレクトリの
リストを参照してください。

マニュアルによる回復

前のセクションのシナリオは全てのサーバのデータを
回復したいという前提です。しかし、もしリカバリー
を行いたい理由があるSQLステートメントに
よってデータが予期せずに消去されてしまい、単にバイナリー
ログを使用した回復では同じことが起こる場合には
どうしましょうか。そのような場合は上記のように
mysqlbinlogを実行しますがmysqlにパイプするので
はなくテキストファイルに格納して、必要な
ものだけを選ぶ編集をします。たとえば以下のようです。

mysqlbinlog /var/log/mysql/bin.123456 \
> /tmp/mysql_restore.sql

このコマンドは/tmpディレクトリに簡単なテキスト
ファイルを生成します。 viやnotepad.exeで編集して
ください。ワードプロセッサは使わないでください。
ファイルにバイナリーのフォーマット用のコード
を付着させるかも知れませんから。そういうものがあると
mysqlに渡したときに問題が起こります。必要でないSQL
ステートメントを除去しリストアーのファイルをセーブして
以下のように処理します。

mysql -u root -pmypwd \
--socket=/tmp/mysql_restore.sock \
< /tmp/mysql_restore.sql

この際レスザンのサインはスタンダード入力をリディレクト
するのに使います。

リカバリー

MySQL4.1.4 からmysqlbinlogに幾つかのオプションが追加されました。
バイナリー・ログを使っての回復の微調整が容易になりマニュアル
での作業を必要としなくなりました。--start-date
と--stop-dateオプションなどです。例えば2005年4月20日
きっかりに大きなテーブルを除去するSQLステートメントを
実行したとします。昨夜のバックアップをリストアーして
mysqlbinlogを以下のように実行します。

mysqlbinlog --stop-date="2005-04-20 9:59:59"
/var/log/mysql/bin.123456 |
mysql -u root -pmypwd \
--socket=/tmp/mysql_restore.sock

これで--stop-dateオプションで与えられている日時まで
の全てのデータを回復します。何時間も経ってから
誤ったSQLステートメントを発見しなかったのであれば、その時点
からのすべての動きをリカバーしたいでしょう。以下の
ように出来ます。

mysqlbinlog --start-date="2005-04-20 10:01:00" \
/var/log/mysql/bin.123456 \
| mysql -u root -pmypwd \
--socket=/tmp/mysql_restore.sock

この例では10:01am以降からログされたSQLステートメントが実行されます。
昨夜のダンプファイルとmysqlbinlogの2行を実行することで
10:00amの一秒前までと10:01amの後の全てをリストアーします。
ログを見てきっちりとした時間を確かめするべきです。次の
セクションでどうするかを説明します。

位置によるリカバリー

特定の時間を使用する代わりに、mysqlbinlogの他の
2つのオプションを使えます。すなわち、--start-positionと
--stop-positionです。スタートとストップのオプションと同じ
ように動作しますが、ログの位置を指定します。
ログでの位置を使うことでもっと正確な回復ができる
かもしれません。これは特に問題があったSQLステートメント
が実行された時点でたくさんのトランザクションが起こった
場合に正確に指定できます。位置を確定するためには、誤った
トランザクションが実行された時期をstart・stop timeを
指定してmysqlbinlogを実行して結果をテキストファイルに
落とします。以下のようにします。

mysqlbinlog --start-date="2005-04-20 9:55:00" \
--stop-date="2005-04-20 10:05:00" \
/var/log/mysql/bin.123456 \
> /tmp/mysql_restore.sql

これは/tmpディレクトリーに誤ったSQLステートメントが
実行された辺りのSQLステートメントを含む小さなテキスト
ファイルを生成します。このファイルをエディター
で開き、繰り返したくないステートメントを除去します。
一旦リカバリーを止めたい時点とリカバリーを再び
始める時点が分かると、その位置を記録します。この位置
はlog-posの後に番号をつけます。バックアップ・ファイルを
リストアーした後、位置の番号を持って、以下を
実行します。

mysqlbinlog --stop-position="368312" \
/var/log/mysql/bin.123456 \
| mysql -u root -pmypwd \
--socket=/tmp/mysql_restore.sock

mysqlbinlog --start-position="368315" \
/var/log/mysql/bin.123456 \
| mysql -u root -pmypwd \
--socket=/tmp/mysql_restore.sock

最初のラインはstopの位置までの全てのトランザクション
を回復します。次のラインはスタートの位置から最後まで
の全てのトランザクションを回復します。ところでそれぞれ
のSQLステートメントが記録される前にmysqlbinlog
の出力はSET TIMESTAMPステートメントがありますので、
回復されたデータと関連するMySQLのログはトランザクション
が実行された時間とマッチします。

結論

バイナリー・ロギングでMySQLの標準インストレーションが
あればある特定の時点に回復できます。肝心なことは定期的
にバックアップを行い、ログをフラッシュすることです。頻度は
それぞれの特定のニーズやポリシーによります。こういう
用意があれば、問題があった時に迅速に正確に回復するプロセス
を熟知するだけです。ここで説明した方法を行うのに
必要な時間がない場合は、特にデータをリカバーする
際に他のユーザに使用を許さないという制限を考慮すると、
他の方法でデータを守る方法を考えリプリケーションやクラスター
なんどの方法を考えるべきです。


[前][次][番号順一覧][スレッド一覧]