メインコンテンツへ移動

ディスクスペースの再利用について

MongoDBインスタンスでデータを削除した場合、削除されたデータの使用していたストレージは「未使用領域」としてマークされます。その後、同じコレクションに新たなデータが書き込まれる際、通常はこの未使用領域が直接活用されます。ただし、この未使用領域は他のコレクションでは再利用できません。こうした未使用領域は「ディスク断片」と呼ばれ、断片が増加するとディスクの利用効率が低下します。

ディスクスペースの再利用方法には、compactコマンドの利用とデータファイルの再構築の2種類があります。

  • compactコマンド:コレクション単位で実行します。各コレクションごとに圧縮処理を行う必要があります。
  • データファイルの再構築:データベースインスタンス全体で実施します。より広範囲かつ包括的な処理となります。

compact​

注意事項​

  • 事前にデータベース全体のバックアップを必ず取得してください。
  • MongoDB 4.4未満のバージョンでは、compactコマンドの実行によってコレクションが属するデータベースがロックされ、対象データベースの読み書き処理がすべてブロックされる可能性があります。ビジネスの閑散時間帯やバージョンアップ後にご実施ください。詳細はMongoDB公式ドキュメントをご参照ください。
  • compactコマンドによる断片領域の再利用処理時間は、コレクションのデータ量やシステム負荷、ディスク性能等に応じて異なります。実行中はCPU・メモリー使用率が一定程度上昇します。
  • MongoDB 4.4.9未満では、compactコマンド実行中のノードは強制的にRECOVERING状態となります。長期化するとPRIMARYノードとのデータ同期不可となる場合があります。
  • MongoDB 4.4.9~4.4.17では、compactコマンド実行中のノードはSECONDARY状態を維持しますが、PRIMARYノードとのデータ同期は依然行えません。
  • MongoDB 4.4.17以上では、SECONDARYノードでcompactコマンド実行中でもPRIMARYノードからのデータレプリケーションが維持されます。compactコマンドの運用は、可能な限りMongoDB 4.4.17以上での実行を推奨します。
  • 下記条件ではcompactコマンドを実行しても効果がほとんど得られません。詳細はソースコードをご参照ください。
    • 物理コレクションサイズが1MB未満
    • ファイルの最初の80%分に未使用ストレージが20%未満しか存在しない場合、または最初の90%分に未使用ストレージが10%未満しか存在しない場合
  • compactコマンドによって必ずしも全ての未使用領域が再利用されるとは限りません。意図した量の領域を解放できない場合は、コマンドの再実行を検討してください。ただし短期間で頻繁に実行することは推奨されません。

推定再利用可能なディスク断片量の確認​

  1. 対象コレクションが存在するデータベースへ切り替えます。

    use database_name
    • database_nameは該当データベース名です。
  2. コレクションの断片領域サイズを確認します。

    db.collection_name.stats().wiredTiger["block-manager"]["file bytes available for reuse"]
    • collection_nameは対象コレクション名です。

    結果例:

    1485426688

    この値が、推定される再利用可能なディスク断片量(単位:byte)です。

シングルノード・レプリカセットインスタンスへの処理​

シングルノード​

ノードが1つだけの場合、対象インスタンス内のコレクションに対してcompactコマンドを実行するだけです。

レプリカセット​

複数ノードの構成では、以下手順に従います。

  1. いずれかのSECONDARYノードでcompactコマンドを実行します。同様の処理を、すべてのSECONDARYノードに順次実施してください。
  2. プライマリノードの再割当を行います。現PRIMARYノードでrs.stepDown()メソッドを用い、PRIMARYノード降格と新PRIMARYノードの選挙をトリガーします。降格後、該当ノードがSECONDARYとなり新PRIMARYノードが選出された時点でcompactコマンドを実行します。
    • PRIMARYノードで強制実行する場合はforceパラメータを付与します。
    db.runCommand({compact:"collection_name",force:true})

compact操作手順​

  1. mongo shellでデータベースノードへ接続します。

  2. 対象コレクションが存在するデータベースへ切り替えます。

    use database_name
  3. 対象コレクションでcompactコマンドを実行します。

    db.runCommand({compact:"collection_name"})
    • collection_nameはコレクション名です。

    正常終了時:

    { "ok" : 1 }

データファイルの再構築​

注意事項​

  • 作業前には必ずデータベース全体のバックアップを取得してください。
  • ファイル再構築に要する時間は、コレクションのデータ量やシステム負荷、ディスク性能に左右されます。

シングルノードの場合​

  1. アプリケーションサービスを停止します。

  2. MongoDBデータベースを停止します。

  3. mongodの--repairパラメータを使用し、データファイルを再構築してディスクスペースを回収します。

    mongod --repair --dbpath /data/mongodb/
    • /data/mongodb/はMongoDBデータディレクトリです。
    • 実行中は操作を遮断しないでください。データの整合性が損なわれ、DB起動不可となる懸念があります。
  4. MongoDBデータベースを起動します。

レプリカセットの場合​

SECONDARYノード上のデータを削除し、MongoDBレプリカセット内部の同期機能によってデータファイルを再構築します。

  1. 任意のSECONDARYノードで、現在ノード内のデータ(keyfileを除く)を全て削除します。

    find /data/mongodb/ -mindepth 1 ! -name 'keyfile' -exec rm -rf {} +
    • /data/mongodb/ディレクトリ内のkeyfileファイル以外全てのファイル・サブディレクトリが削除されます。
  2. 現ノードを再起動します。

  3. rs.status()コマンドでノード状態を確認します。同期中はSTARTUP2として表示され、完了後はSECONDARY状態になります。

  4. 前段で同期完了(SECONDARY状態化)した後、残りのSECONDARYノードにも同処理を順次実施します。

  5. PRIMARYノードでは、rs.stepDown()メソッドを用いて再選挙をトリガーします。PRIMARY降格・新PRIMARY選出後に、そのノードで同様のデータ削除~再起動作業を行います。