はじめに
mongoDBに保存していたデータが壊れてしまって修復するのが大変だったので、記録しておきます。
英語で書かれた以下の記事が役に立ちました。この記事の内容を翻訳しつつまとめます。
問題
Dockerコンテナ上でbashを起動し、mongod
を実行すると、Abortedになってしまう。
% docker-compose exec mongo bash
# mongod
...
...
...
Aborted
修復前のdocker-compose.ymlは以下です。
_dataというmongoDBのデータベースをマウント。
version: '3.1'
services:
mongo:
image: mongo
restart: always
command: tail -f /dev/null
ports:
- 27017:27017
volumes:
- type: bind
source: "./_data"
target: "/data/db"
解決
まずは、修復したコレクションを入れるフォルダと、修復前のコレクションを入れるフォルダを作成する。
New Database collection files are stored in: /data/new-db
Old Database collection files exist in: /data/old-db
コレクションを修復するためのdocker-compose.ymlは以下。
自分の場合、./data配下にnew-db, old-dbフォルダを作成してマウントしました。
version: '3.1'
services:
mongo:
image: mongo
restart: always
command: tail -f /dev/null
ports:
- 27017:27017
volumes:
- type: bind
source: "./data"
target: "/data"
次に、コンテナを起動しコンテナに入り、パスを指定してmongod
を実行する。
% docker-compose up
% docker-compose exec mongo bash
# mongod --dbpath /data/new-db
そしたら、別のターミナル画面から、mongo
を起動し、データベースを確認。
空っぽの3つのデータベースがあります。
% docker-compose exec mongo bash
# mongo
MongoDB shell version v5.0.5
...
...
...
> show dbs;
admin 0.000GB
config 0.000GB
local 0.000GB
ここで、修復したデータを入れるための新しいデータベース, コレクションを作成し、
ダミーのデータをコレクションに入れます。count()
を実行するとダミーで入れたデータ数1が出力されます。
ここでダミーのデータを入れるのは後でmongoDBを操作できるようにするためだそうです。
It’s important to note that you MUST put some document/data inside a collection in order to be able to manipulate MongoDB later on.
> use Recovery
switched to db Recovery
> db.newDummyCollection1.insert({arbitrary: "value"})
WriteResult({ "nInserted" : 1 })
> db.newDummyCollection1.count()
1
次のステップは、作成したコレクションが保存されているディスクの場所を確認することです。
> db.newDummyCollection1.stats()
{
"ns" : "Recovery.newDummyCollection1",
"size" : 43,
"count" : 1,
...
...
...
"uri" : "statistics:table:collection-*--****************",
長いJSONが出力されますが、その中からuri
オブジェクトを見つけます。
これにより、作成したコレクションの完全なファイル名とディスク上の位置は、
/data/new-db/collection-*--****************.wt
だと分かります。
そしたら、Ctl+C
でmongodを終了し、Ctl+D
でmongoシェルを終了します。
ここからが修復パートです。
修復したいコレクションのファイルを/data/old-dbに置いておきます。
修復したいコレクションのファイルで、作成した新しいコレクションを上書きします。
# cp /data/old-db/collection-**–*************.wt \
/data/new-db/collection-*-**************.wt
上書きできたら遂に修復の時です。
# mongod --dbpath /data/new-db --repair
...
...
...
"attr":{"exitCode":0}}
"exitCode":0
は正常に終了したということでしょう(たぶん)。
ちゃんと修復できたか見てみます。
# mongod --dbpath /data/new-db
# mongo
MongoDB shell version v5.0.5
...
...
...
> show dbs;
Recovery 0.022GB
admin 0.000GB
config 0.000GB
local 0.000GB
> use Recovery
switched to db Recovery
> db.newDummyCollection1.count()
984
count()
の実行結果が1から増えてますね。修復できたみたいです!!
まとめ
最終的なディレクトリの構成はこんな感じになりました。
% tree -L 3
.
├── data
│ ├── configdb
│ ├── db
│ ├── new-db
│ │ ├── WiredTiger
│ │ ├── WiredTiger.lock
│ │ ├── WiredTiger.turtle
│ │ ├── WiredTiger.wt
│ │ ├── WiredTigerHS.wt
│ │ ├── _mdb_catalog.wt
│ │ ├── collection-0--4457885176236347020.wt
│ │ ├── collection-0--987413417896500712.wt
│ │ ├── collection-2--4457885176236347020.wt
│ │ ├── collection-4--4457885176236347020.wt
│ │ ├── diagnostic.data
│ │ ├── index-0-6915199917482120785.wt
│ │ ├── index-1--4457885176236347020.wt
│ │ ├── index-3--4457885176236347020.wt
│ │ ├── index-5--4457885176236347020.wt
│ │ ├── index-6--4457885176236347020.wt
│ │ ├── journal
│ │ ├── mongod.lock
│ │ ├── sizeStorer.wt
│ │ └── storage.bson
│ └── old-db
│ └── collection-7-8406677046678898115.wt
└── docker-compose.yml
7 directories, 20 files
間違い等あればご指摘いただけると嬉しいです。お疲れ様でした。