fbpx

よくある質問

MongoDB FAQ #7: MongoDBの診断

このドキュメントは診断に関する質問や問題に関するよくある質問にお答えするものです。

探している回答が見つからない場合、他のFAQをご確認いただくか、MongoDB User メーリングリストにご質問を投稿してください。

1. 予期せずに実行が中止されたmongodプロセスに関する情報はどこにありますか?

もし mongod が UNIX もしくは UNIX ベースのプラットフォームで予期せずにシャットダウンした場合、かつもし mongod がシャットダウンやエラーメッセージのログの記録に失敗した場合、システムログの MongoDB に関連するメッセージを確認してください。例えば、/var/log/messages に格納されているログに対しては、次のコマンドを使用します:

sudo grep mongod /var/log/messages
sudo grep score /var/log/messages
2. TCP keepalive タイムは MongoDB のデプロイに影響を及ぼしますか?

もしその他の正当な理由もなく、クライアントとサーバ間に、もしくはクライアントとシャードされたクラスタのメンバー間に、もしくはクライアントとレプリカセット間にソケットエラーが生じた場合、TCP keepalive 値(例えば Linux システムのtcp_keepalive_time 値)を確認してください。標準的な keepalive 時間は7200秒(2時間)です。しかしながら、異なるディストリビューションやmacOSの場合は設定が異なるかもしれません。

MongoDBでは、一般的に120秒以下のkeepalive時間の方がより適切に動作します。

もしMongoDBのデプロイで keepalive 関連の問題に直面している場合、MongoDB プロセスをホストしている全てのホストの keep alive 値を変更しなくてはなりません。これには、mongos または mongod プロセスをホストするすべてのマシンと、MongoDB に接続するクライアントプロセスをホストするすべてのマシンが含まれます。

注:非Linuxシステムでは、600秒(10分)以上の値はmongodならびにmongosでは無視されます。Linux では300秒(5分)よりも大きな値はmongod および mongosソケット上で最大300秒と上書きされます。

Linux システム向け:

  • keep alive 設定を見るには、次のコマンドのいずれかを使用してください:

sysctl net.ipv4.tcp_keepalive_time

もしくは:

cat /proc/sys/net/ipv4/tcp_keepalive_time

 値は秒単位です。

 注: パスにはipv4が含まれますが、tcp_keepalive_time値はIPv4とIPv6の両方に適応されます。

  •  tcp_keepalive_time値を変更するには、次のコマンドのいずれかを使用できます。

sudo sysctl -w net.ipv4.tcp_keepalive_time=<値>

もしくは:

echo <値> | sudo tee /proc/sys/net/ipv4/tcp_keepalive_time

 これらの操作は、システムの再起動を行うと持続しません。設定を持続させるには、/etc/sysctl.confに次の一行を追加します:

net.ipv4.tcp_keepalive_time = <値>

 Linuxでは、mongodおよびmongos プロセスは、5分以上のkeepalive値を上書きすることで、keepalive値を自身のソケット上で最長300秒(5分)になるよう制限しています。

macOSシステム向け:

  • keep alive設定を表示するには、次のコマンドを発行します:

sysctl net.inet.tcp.keepinit

  •  net.inet.tcp.keepinit値を変更するには、次のコマンドを使用できます:

sysctl -w net.inet.tcp.keepinit=<値>

TCP keepalive設定の前述の方法は永続的には設定されないので、コンピュータもしくはシステムの再起動をする度にその都度値を再設定する必要があります。 TCP keepalive値を永続的に設定する手順については、ご使用のOSのドキュメントをご確認ください。

Windowsシステム向け:

  •  keep alive設定を表示するには、次のコマンドを発行します:

reg query HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters /v KeepAliveTime

 レジストリ値はデフォルトでは存在しません。もし値が存在しない場合に使用されるシステムのデフォルト値は、7200000ミリ秒または16進数で0x6ddd00です。

  • KeepAliveTime値を変更するには、Administratorというユーザで実行したCommand Promptで次のコマンドを使用します。 値は16進数で指定します。

reg add HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\ /t REG_DWORD /v KeepAliveTime /d <値>

 Windowsユーザは、Windowsシステム上でMongoDBをデプロイするためのkeep alive 設定の情報に関して、Technetサイト上のWindowsサーバ向けKeepAliveTimeに関する記事を参考にしてください

新しいシステム全体のkeepalive設定を有効にするためには、mongodおよびmongos プロセスを再起動する必要があります。

3. MongoDBでは、なぜ多くの “Connection Accepted”イベントのログが記録されるのでしょうか?

もしMongoDBログ内に、非常に多くの接続および再接続メッセージが書かれている場合、クライアントは頻繁にMongoDBサーバに接続したり接続を切断しているということを意味しています。これはCGIのようなリクエストプーリングを使用しないアプリケーション(と一緒にMongoDBを使用する場合)の通常の動作です。接続のオーバーヘッドを減らすために、FastCGI、Apache Module、またはその他のタイプの永続的なアプリケーションサーバを使用することをご検討ください。

 これらの接続がパフォーマンスにインパクトを与えない場合、実行時の「quiet」オプションまたはコマンドラインオプションである「--quiet」を使用して、これらのメッセージのログへの出力を抑制することが可能です。

4. MongoDBを監視するためにどのようなツールが利用できますか?

バージョン4.0以降、MongoDBはスタンドアロンおよびレプリカセット向けに無料でCloud監視(ツール)を提供しています。無料のCloud監視(ツール)では、デプロイに関する次の情報を提供します:

  •  オペレーション実行回数
  • メモリ使用率
  • CPU使用率
  • オペレーション数

より詳細の情報は、こちら(Free Monitoring)をご参照ください。

MongoDB Cloud Manager、およびオンプレミス環境におけるMongoDB Enterprise Advancedに含まれるOps Managerは監視機能を含んでいます。MongoDB Cloud ManagerおよびOps Managerは、稼働するMongoDBから情報を収集し、視覚化し、これらのデータを基にアラームを送信することが可能です。

詳細はこちら(MongoDB Cloud Manager documentation および Ops Manager documentation)をご参照ください。

サードパーティのツールの全リストは、Monitoring for MongoDBドキュメンテーションをご参照ください。

5. MMAPv1 ストレージエンジンのメモリ診断

非推奨:

MongoDB 4.0ではMMAPv1 ストレージエンジンを非推奨とし、今後のリリースでMMAPv1は削除される予定です。MMAPv1 ストレージエンジンのデプロイをWiredTigerストレージエンジンへ変更するには、次をご参照ください:

swap space を設定する必要はありますか?

常にswap space を保持するようにシステムを設定してください。swap なしでは、メモリー残量がわずかしかない場合、メモリリークの場合、同一のメモリを複数のプログラムが使用している場合などに、システムの信頼性が低下する可能性があります。swap space は、システムへの過剰な圧力をシステム全体の機能に影響を与えることなく逃がすもの、例えるなら蒸気を逃がすバルブのようなものだとお考え下さい。

とはいうものの、MongoDBを実行しているシステムでは、通常の操作のために swap を必要とはしません。データベースファイルはメモリマップされており、MongoDBのメモリ使用の大半を占めるはずです。従って、通常の操作ではmongodがswap spaceを使用することはありえないのです。OSはswapを必要とせずに、メモリマップされたファイルからメモリをリリースします。そしてMongoDBはswapシステムを必要とせずにデータファイルにデータを書込むことが可能です。

”ワーキングセット”とは何ですか?

ワーキングセットとは、クライアントが最も頻繁にアクセスするデータの一部分を意味します。

ワーキングセットのサイズはRAMに収める必要がありますか?

ワーキングセットはメモリ内に残すと高いパフォーマンスを達成できます。さもないと、ランダムなディスクIOが多発し、SSDを使用していない限り、かなり動作が遅くなる可能性があります。

ワーキングセットのサイズの管理上、特に注意して見ておくべき領域はインデックスのアクセスパターンです。インデックス内のランダムな場所に挿入する場合(ハッシュによってランダムに生成されたIDでも起こりえるように)、インデックス全体を更新し続けます。もし代わりに、IDをざっと昇順(例えば、ランダムIDと連結した日)で作成することができれば、すべての更新はb-treeの右側で行われ、インデックスページのワーキングセットのサイズはずっと小さくなります。

データベースと仮想サイズがRAMよりはるかに大きい場合は問題ありません。

アプリケーションにどれくらいのRAMが必要か計算するにはどうすればよいでしょうか?

必要なRAMの容量は、次のいくつかの要因(これら以外にも要因はありますが)によって異なります:

  • データベースストレージとワーキングセットの関係性
  • OSのLRU(Least Recently Used)用キャッシュストラテジー
  • ジャーナリングによる影響
  • 追加でRAMが必要なときに、検知すべきページフォルトやその他のMongoDB Cloud Managerゲージ数や比率
  • 各データベース接続スレッドには、最大1 MBのRAMが必要です。

MongoDBはディスクからデータをメモリにロードする時にOSに従います。MongoDBは単純にすべてのデータファイルをメモリマップし、データのキャッシュはOSに依存します。OSは通常、メモリが不足しているときにRAMから最も使用頻度の少ない(最長時間未使用の)データを破棄します。例えば、クライアントが文書よりもインデックスにより頻繁にアクセスする場合、インデックスはRAM内に残る可能性が高くなりますが、それぞれの使用状況によって異なります。

どれだけのRAMが必要か計算するには、ワーキングセットのサイズあるいはクライアントが最も頻繁に使用するデータを計算する必要があります。これは、アクセスパターンや、どのインデックスを持っているのか、そしてドキュメントのサイズがどれくらいかによって異なります。MongoDBは接続モデルごとにスレッドを使用するため、アクティブまたはアイドルのいずれの場合でも、各データベース接続には最大1 MBのRAMが必要になります。

もしページフォルトが頻繁に起きなければ、ワーキングセットがRAMに収まっていることを意味します。もしページフォルト率がそれよりも高ければ、パフォーマンス低下の危険性があります。これはスピンディスク(=HDD)よりもSSDドライブにおいてはさほど深刻ではありません。

UNIXのtopコマンドでメモリ統計を読み取るにはどうしたらよいでしょうか?

mongodメモリマップされたファイルを使用するため、topコマンドのメモリ統計は特別な方法で解釈する必要があります。大きなデータベースでは、VSIZE (virtual bytes)はデータベース全体のサイズになる傾向があります。もしmongodで他のプロセスが実行されていない場合、RSIZE(常駐バイト)は、ファイルシステムのキャッシュ内容をカウントするため、マシンの合計メモリを表します。

Linuxシステムにおいては、vmstatコマンドを使用し、システムがどうメモリを使用するかを見ることができます。macOSシステムでは、vm_statを使用します。

6. WiredTigerストレージエンジンのメモリ診断

ワーキングセットのサイズはRAMに収める必要がありますか?

いいえ、ありません。

もしキャッシュに追加データを読込むための十分な領域がない場合、WiredTigerはページをキャッシュから削除して空き容量を増やします。

注:

WiredTiger 内部キャッシュのサイズは、storage.wiredTiger.engineConfig.cacheSizeGB で制限されています。OS は使用可能な状態のメモリをファイルシステムキャッシュ用に使用します。これにより圧縮されたMongoDBデータファイルがメモリに保持されます。加えて、OSは使用可能な状態のRAM をファイルシステムブロックおよびファイルシステムキャッシュをバッファーするために使用します。

もしOSのバッファ量を増やしたい場合は、WiredTiger内部キャッシュのサイズを小さくしなければならない場合があります。

WiredTiger 内部キャッシュのサイズ値のデフォルトは、マシン当たり一つのmongod インスタンスがあると仮定しています。もし1台のマシンが複数のMongoDB インスタンスを保持している場合、他のmongod インスタンスを許容させるために設定を下げなくてはなりません。

システム内の利用可能なRAM全てへのアクセスがないコンテナ(例:lxc、cgroups、Docker 等 )で mongod を実行する場合:storage.wiredTiger.engineConfig.cacheSizeGB をコンテナ内の利用可能なRAM の量以下の値に設定しなくてはなりません。正確な値は、コンテナ内で実行中の他のプロセスに依ります。

キャッシュおよび削除の統計には serverStatusコマンドをご利用ください。wiredTiger.cacheフィールドは、キャッシュおよび削除に関する情報を保持しています。

...
"wiredTiger" : {
...
"cache" : {
"tracked dirty bytes in the cache" : <値>,
"bytes currently in the cache" : <値>,
"maximum bytes configured" : <値>,
"bytes read into cache" :<値>,
"bytes written from cache" : <値>,
"pages evicted by application threads" : <値>,
"checkpoint blocked page eviction" : <値>,
"unmodified pages evicted" : <値>,
"page split during eviction deepened the tree" : <値>,
"modified pages evicted" : <値>,
"pages selected for eviction unable to be evicted" : <値>,
"pages evicted because they exceeded the in-memory maximum" : <値>,
"pages evicted because they had chains of deleted items" : <値>,
"failed eviction of pages that exceeded the in-memory maximum" : <値>,
"hazard pointer blocked page eviction" : <値>,
"internal pages evicted" : <値>,
"maximum page size at eviction" : <値>,
"eviction server candidate queue empty when topping up" : <値>,
"eviction server candidate queue not empty when topping up" : <値>,
"eviction server evicting pages" : <値>,
"eviction server populating queue, but not evicting pages" : <値>,
"eviction server unable to reach eviction goal" : <値>,
"pages split during eviction" : <値>,
"pages walked for eviction" : <値>,
"eviction worker thread evicting pages" : <値>,
"in-memory page splits" : <値>,
"percentage overhead" : <値>,
"tracked dirty pages in the cache" : <値>,
"pages currently held in the cache" : <値>,
"pages read into cache" : <値>,
"pages written from cache" : <値>,
},
...

wiredTiger.cache.bytescurrently in the cache および wiredTiger.cache.tracked dirty bytes in the cache などの主要なキャッシュおよび削除の統計情報の解説は、wiredTiger.cacheをご覧ください。

WiredTiger内部キャッシュサイズを調整するには、storage.wiredTiger.engineConfig.cacheSizeGB および--wiredTigerCacheSizeGBをご覧ください。WiredTiger 内部キャッシュのサイズをデフォルト値より多い値に設定することは避けてください。

アプリケーションにはどれくらいのRAMが必要か計算するにはどうすればよいでしょうか?

WiredTiger を使用する場合、MongoDB はファイルシステムキャッシュとWiredTiger 内部キャッシュの両方を活用します。 

3.4以降では、WiredTiger 内部キャッシュは以下の2つのうちでより大きい方を使用します: 

  • (RAM - 1 GB) の50% もしくは
  • 256MB

例えばシステム全体で4GBのRAMを有する場合、WiredTigerは1.5GB(=0.5*(4GB-1GB))のRAMをキャッシュとして使用します。一方システムが1.25GBしかRAMを持たない場合、WiredTigerのキャッシュは256MBとなります。これは"(RAM - 1 GB) の50%"、つまり0.5*(1.25GB-1GB)=128MBよりも256MBの方が大きいからです。

WiredTiger は 全てのコレクションには Snappy block compression を、そして全てのインデックスには prefix compression をデフォルトで使用します。Compression のデフォルトは、グローバルレベルで設定可能です。また、コレクションおよびインデックス作成時に、コレクション毎、インデックス毎でも設定できます。

WiredTiger 内部キャッシュ内のデータとディスク上のデータのフォーマットは、それぞれ異なる内部表現が使用されています:

  • ファイルシステムキャッシュ内のデータは、データファイル圧縮の利点を含めて、オンディスクフォーマットと同じです。WiredTigerが生成したオンディスクキャッシュは、OSでも使用され、ディスクIOの低減を期待することができます。
  • WiredTiger 内部キャッシュでロードされたインデックスはオンディスクフォーマットとは異なる内部データ表現を保持しますが、RAM 使用量を抑えるための index prefix compression の恩恵は受けられます。Index prefix compression はインデックスされたフィールドから一般的な prefixes の重複排除を行います。
  • WiredTiger 内部キャッシュ内のコレクションデータは圧縮されておらず、オンディスクフォーマットとは異なる内部表現を使用しています。Block compression を使用することでオンディスクストレージを大幅に節約できますが、サーバーからの操作を可能にするため、データは使用する前にサーバによって圧縮が解除されます。

MongoDB は、ファイルシステムキャッシュを介すことによって、WiredTiger キャッシュもしくは他のプロセスによって使用されていない全てのメモリを自動的に使用します。

WiredTiger内部キャッシュサイズを調整するには、storage.wiredTiger.engineConfig.cacheSizeGB および--wiredTigerCacheSizeGBをご覧ください。WiredTiger 内部キャッシュのサイズをデフォルト値より多い値に設定することは避けてください。

注:

WiredTiger 内部キャッシュのサイズは、storage.wiredTiger.engineConfig.cacheSizeGB で制限されています。OS は使用可能な状態のメモリをファイルシステムキャッシュ用に使用します。これにより圧縮されたMongoDBデータファイルがメモリに保持されます。加えて、OSは使用可能な状態のRAM をファイルシステムブロックおよびファイルシステムキャッシュをバッファーするために使用します。

もしOSのバッファ量を増やしたい場合は、WiredTiger内部キャッシュのサイズを小さくしなければならない場合があります。

WiredTiger 内部キャッシュのサイズ値のデフォルトは、マシン当たり一つのmongod インスタンスがあると仮定しています。もし1台のマシンが複数のMongoDB インスタンスを保持している場合、他のmongod インスタンスを許容させるために設定を下げなくてはなりません。

もしシステム内の利用可能なRAM全てへのアクセスがないコンテナ(例:lxc、cgroups、Docker 等 )で mongod を実行する場合、 storage.wiredTiger.engineConfig.cacheSizeGB をコンテナ内の利用可能なRAM の量以下の値に設定しなくてはなりません。正確な値は、コンテナ内で実行中の他のプロセスに依ります。

キャッシュおよびキャッシュエビクションの統計は、serverStatusコマンドから返された wiredTiger.cache フィールドで閲覧可能です。

7. シャードされたクラスタの診断

正常なシャードされたクラスタを維持するのに最も重要な2つの要因は次のとおりです:

デプロイにとって最適なシャードキーを選択し、現在のリソースが飽和してしまう状態になるずっと前に、常にクラスタに容量を追加するようにすれば、シャーディングで発生するほとんどの問題を回避することが可能です。本番環境で発生する可能性のある特定の問題については、この先を引き続きお読みください。

新規のシャードされたクラスタ内で、すべてのデータが1つのシャードに残るのはどうしてですか?

シャードされたクラスタにデータを投入する場合、(シャーディングが十分に機能するほどの)十分なデータが必要です。シャーディングは各シャードがほぼ同じ数のチャンクを持つまで、シャード間のチャンクを移動することによって機能します。

チャンクサイズのデフォルト値は64メガバイトです。クラスタ内のチャンクの不均衡がマイグレーションの閾値を超えるまで、MongoDB は移行を開始しません。この挙動によって、クラスタ全体のパフォーマンスを悪化させかねない不要なチャンクマイグレーションを防止します。

シャードされたクラスタをデプロイした直後は、シャーディングを効率的におこなうための十分なデータを保持しているか確認してください。64メガバイトチャンクを8個以上作成するのに十分なデータを保持していない場合、全データは1つのシャード上に存在し続けます。チャンクサイズ設定を低くするか、クラスタにデータを追加してください。

関連する問題として、システムは挿入時もしくは更新時のみチャンクを分けます。つまりシャーディングを設定したあと続けて挿入および更新の操作を行わない場合はデータベースはチャンクを作成しません。アプリケーションがデータを挿入するのを待つか、もしくは手動でチャンクを分けてください

最後に、シャードキーのカーディナリティが低い場合、MongoDBはデータ間の十分なスプリットを作成することができません。

シャードされたクラスター内で1つのシャードが不均衡なトラフィックを受けるのはなぜでしょうか?

場合によっては、1つのシャードもしくはクラスタのサブセットが不均衡なトラフィックおよびワークロードを受ける場合があります。ほとんどの場合、これは書込みのスケーラビリティを考慮していないシャードキーの指定によるものです。

この現象は、「ホットチャンク(アクセスが集中するチャンクの意)」でも起きえます。この場合、これらのチャンクを分けて一部を(他のホストへ)マイグレートすることで解決できます。

最悪の場合、このパターンを修正するためにデータを再シャードして別のシャードキーを選択することも検討してください。

シャードされたクラスタのバランシングを阻害するものは 何ですか?

シャードされたクラスタをデプロイした直後であれば、こちら「新規クラスター向けトラブルシューティング:データが一つのシャード上に残っている場合」をご参照ください。

当初はクラスタがバランスされていたが、その後のデータ配置が均一でなくなった場合、以下の原因が考えられます:

  • クラスタから相当量のデータを削除もしくは移動させたため。データを追加した場合、(追加したデータの)シャードキーが異なる分散状態であった場合
  • シャードキーカーディナリティが低く、MongoDBがチャンクをこれ以上分けられないため
  • バランサーがクラスターにデータを配置するよりも、データセットが増加する速度が早いため。これは一般的ではなく、考えられる要因は次の通りです:

    • データの増加速度に比べて、バランシングのための時間が短すぎるため。
    • 更なるデータ移行を必要とする書込み操作が不均一に配置されている為。この問題を解決するには別のシャードキーを選択しなければならないかもしれません。
    • シャード間のネットワーク遅延のため、チャンクのマイグレーション完了までに時間がかかる。ネットワーク設定およびシャード間の接続を調査してください。

なぜチャンクのマイグレーションがシャードされたクラスタのパフォーマンスに影響を与えるのですか?

マイグレーションがクラスタもしくはアプリケーションのパフォーマンスに影響を与える場合は次のオプションを検討してください。どのオプションを選ぶかはどのような影響が出ているかに依ります。

  1. マイグレーションがクラスタの動作を阻害することが散発的であれば、バランシングウィンドウを制限することでピーク時のバランシング動作を防ぐことができます。データがまたバランス不均衡に陥らないための十分な時間を確保してください。
  2. バランサーが常にチャンクをマイグレートしていてクラスタ全体のパフォーマンスに影響を及ぼしている場合:

アプリケーションがシャードキーによってすべての書込みを一つのシャードに向けている可能性もあります。このような動作パターンでは、全てのデータが書き込まれた直後にバランサーがデータをマイグレーションする場合があります。その場合、より良い書込みスケーリングを提供してくれるシャードキーと共にクラスタを再デプロイすることを検討してください。