Help us understand the problem. What is going on with this article?

MongoDBで特定処理を除いてスナップショットからoplogによる差分リストアする

More than 3 years have passed since last update.

とりあえずAWSで動かしているとして、スナップショットによるバックアップをしている場合に復旧する手順メモ。
LVMによるスナップショットバックアップなどでも、それほど手順は変わらないはずです。

何か操作ミスが行われた前提とします。

リストアする前に行う作業

当然ながらmongoに対してこれ以上アクセスがないようにします。
mongoを一旦停止して、直接DBを別ポートで起動してしまうのが一番安全です。
マスタに最新のoplogがあるはずなので、マスタのみで行います。

mongod --dbpath /path/to/db --port 37017

リストアにはoplogで差分を埋めることになるので、スナップショットした時間以降のすべてのoplogがあることが前提となります。そのため、必ずスナップショットの間隔がoplogに保存される時間を超えないように監視を必要とします。

  • oplog監視スクリプト例(-A oplog)

https://github.com/sensu-plugins/sensu-plugins-mongodb/blob/master/bin/check-mongodb.py

oplogはデータサイズ固定で古いものから消えていく設定になっているので、普段は1日分取っているけどバッチ処理で一気に流れてしまうということがあり得るので注意が必要です。スナップショットの間隔を狭めるなりoplogのサイズを大きくしておくといいです。

  • oplogサイズ変更手順

https://docs.mongodb.org/manual/tutorial/change-oplog-size/

復旧したいoplogを調べる

mongoのシェルでuse localしてからdb.oplog.rs.find()以降にクエリをつけて差分として取り込む対象を絞っておきます。
oplogにはindexが貼られていないので、対象が多いと調べるのが難しいでしょう。直近の操作ならtsに加えて.sort( {$natural : -1} )をつけて条件を絞ると早かったりします。

oplogをダンプする

下記でダンプできますが、

mongodump --port 37017 -d local -c oplog.rs -o oplogD

この時--query '{ "ts" { $gt: Timestamp(1458790000, 1) } , "ts": { $ne: Timestamp(1458799147, 48) } }'のように条件が付けることが可能です。よって、ここで操作ミスを取り除いたoplogを作成できます。操作ミスが後のクエリに影響を与えるような処理だったら、操作ミス以降のをデータをすべてダンプしないようにしましょう。

ダンプを取った時間よりちょっと前をtsで指定するとダンプ時間の短縮になります。
そのため、スナップショットを取る際に、タグに最新のoplogのタイムスタンプを入れるようにしておくと便利です。最低でも、システムの最新のタイムスタンプは入れておくべきでしょう。

oplogからの差分リストアを行う場合、リストアしようとしているmongoの最新のoplogのタイムスタンプ以前のものは実行をスキップするという処理になるため、余分にoplogを取ってしまってもも問題ありません。。
もしoplogをすべて削除してからリストアによるoplogの差分復旧を行ったら、すべてのoplogが実行されます。

oplogをリストアできるようにしておく

ダンプしたファイルは./oplogD/local/oplog.rs.bsonに吐き出されるので、適当な別ディレクトリを作ってファイル名をoplog.bsonにします。これは単純にmongorestoreの仕様です。

mkdir oplogR
mv oplogD/local/oplog.rs.bson oplogR/oplog.bson

mongoをスナップショットから復旧する

データベース用のEBSとして別領域に分けてある場合には

  1. mongodを終了
  2. mongo用の領域をumount
  3. AWSコンソールから、ボリュームをdetach
  4. AWSコンソールから、スナップショットからボリュームを作ってattach
  5. mongo用の領域をmount

のような手順を踏めばボリュームを交換できます。

oplogから差分を取り込む

oplogのリストア時にレプリケーションが行われているとoplogの実行されないという仕様への対処と、通常のアクセスが来ないように別ポートで

mongod --dbpath /path/to/db --port 37017

で直接mongoを起動します。
この時起動するユーザで新規ファイルは書き込まれてしまうので、復旧後にファイルの権限を戻すようにする必要があります。

起動したら、mongorestore実行してoplogから差分を取り込みます。
この時--oplogLimit <timestamp>で実行するoplogを制限できますが、指定時間以降のものは全く実行しないだけです。よって、mongodumpの時にqueryで処理してあげた方がやりやすいはずです。

mongorestore --port 37017 --oplogReplay oplogD

レプリカでも同様にします。replSetを使わずに起動しているのでoplogのリストアの結果はoplogには記録されません。

レプリケーションを再開する

接続するホスト名など変わっていなければ、元の設定から起動するだけで復旧するはずです。レプリケーションのホストの情報などもmongoはデータベースに持っているためです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away