MongoDBでゆるふわDB体験

第12回MongoDBの監視

はじめに

前回からMongoDBの非機能面に着目していますが、今回はMongoDBの監視について説明します。まず、MongoDBの監視で使うことができる機能やツールを紹介し、その後、これらのツールを用いてどのようにMongoDBを監視するかについて一般的な考え方を紹介します。MongoDBは最新バージョンの2.4を対象としています。

コマンド表記について

$ : コマンドラインで実行するコマンド

監視機能の紹介

ロギング

最初に監視の基本ともいえる、ロギングについて説明します。MongoDBでは何も指定しないと標準出力にログが出力されますが、ファイルに出力する場合は「 --logpath 」オプションにてログの出力先を指定します。

$ mongod --logpath=/var/log/mongodb.log

このままだと、次回起動時にログはローテーションされてしまいます。ログをローテーションせず追記する場合は「--logappend」オプションを用います。

$ mongod --logpath=/var/log/mongodb.log --logappend

ログのレベルは、⁠--verbose」オプションを指定することにより、出力をより多くできます。また、⁠-v」⁠-vv」⁠-vvv」⁠-vvvv」⁠-vvvvv」というオプションもあり、vの数が多いほど詳細に出力されます。逆に「--quiet」オプションを指定すると、最小限の出力になります。

$ mongod --verbose  ←ログ出力を多くする
$ mongod -vvvvv     ←ログ出力を最大限
$ mongod --quiet    ←ログ出力を最小限

リアルタイム監視コマンド

続いて、MongoDBのリアルタイム監視コマンドについて紹介します。次に紹介するコマンドは、mongodが入っているbinディレクトリに入っており、コマンドラインから実行することができます。

コレクションの処理時間順に表示(mongotopコマンド)

mongotopコマンドはtopコマンドのようなコマンドであり、処理に時間がかかっているコレクションを処理時間順に見ることができます。コマンド実行すると、以下のような出力が1秒ごとにひとかたまりずつ出力されます。

mongotopコマンド実行結果(抜粋)
$ mongotop
                      ns       total        read       write              2013-04-17T16:11:44
  sample-db.collection01        13ms         1ms        12ms ←★
  sample-db.collection02        11ms         0ms        11ms
    admin.system.indexes         0ms         0ms         0ms
                       ns       total        read       write              2013-04-17T16:11:45
  sample-db.collection01        16ms         2ms        14ms
  sample-db.collection02        11ms         5ms        11ms
    admin.system.indexes         0ms         0ms         0ms
       (略)

上記の出力結果からは、⁠sample-db.collection01」のコレクションが最も処理時間がかかっており、その中でも書き込みに12ミリ秒費やしていることがわかります。

MongoDB全体の状態を表示(mongostatコマンド)

mongostatコマンドはvmstatのようなコマンドであり、MongoDBサーバ全体のさまざまな統計情報を定期的に表示することができます。コマンドを実行すると以下のような出力が1秒ごとに一行ずつ出力されていきます。

mongostatコマンド実行結果(抜粋)
$ mongostat
insert  query update delete getmore command flushes mapped  vsize    res faults      locked db idx miss %     qr|qw   ar|aw  netIn netOut  conn       time
    *0     *0     *0     *0       0     2|0       0  2.11g  4.51g   946m      0      test:0.0%          0       0|0     0|0   120b     3k     1   01:19:24
    86     *0     *0     *0       0   130|0       0  2.11g  4.51g   974m    132 sample-db:1.8%          0       0|0     0|0    14m    13k     2   01:19:25
   121     *0     *0     *0       0   181|0       0  2.11g  4.51g   994m    181         .:3.2%          0       0|0     0|1    20m    16k     2   01:19:26
   117     *0     *0     *0       0   178|0       0  2.11g  4.51g  1.01g    175         .:3.1%          0       0|0     0|0    20m    16k     2   01:19:27

上記出力では途中から挿入(insertの列)が増加してきて、それに伴い書き込みロックしている割合(locked dbの列)が増加していることがわかります。

統計情報表示メソッド

次に統計情報表示メソッドの説明をします。Mongoシェルでアクセスし、次に紹介するデータベースオブジェクトのメソッドを呼び出すことにより、さまざまな統計情報を表示できます。

MongoDB全体の統計情報(serverStatus()メソッド)

データベースオブジェクトのserverStatus()メソッドを用いることで、MongoDBのサーバの統計情報を詳細に表示することができます。このコマンドは非常に多くの統計情報を出すことができます。たとえば、ページフォルト、B-treeのアクセスレート、開いている接続数、挿入や更新、クエリ、削除の合計数などが含まれます。

serverStatus()メソッド実行結果(抜粋)
> db.serverStatus()
{
        "host" : "mongodb.localdomain",
        "version" : "2.4.1",
        "process" : "mongod",
        "pid" : 1537,
        "mem" : {
                "bits" : 64,
                "resident" : 725,        ←物理メモリ使用量
                "virtual" : 2568,        ←仮想メモリ使用量
                "supported" : true,
                "mapped" : 1136,
                "mappedWithJournal" : 2272
        }

上記の出力結果から、MongoDBの物理メモリ使用量が725MBであり、仮想メモリ使用量が2568MBであることがわかります。

データベースの統計情報(データベースのstats()メソッド)

データベースオブジェクトのstats()メソッドを用いることで、データベースの統計情報を表示することができます。

データベースのstats()メソッド実行結果(抜粋)
> db.stats()
{
        "db" : "sample-db",
        "collections" : 3,        ←コレクション数
        "dataSize" : 1447258292,  ←データサイズ
        "indexSize" : 408800,
        (略)
}

上記の出力結果から、コレクション数が3で、データのサイズが1447258292Byteであることがわかります。

コレクションの統計情報(コレクションのstats()メソッド)

データベースのstats()コマンドと同様に、コレクションのstats()メソッドを用いることで、そのコレクションの統計情報を表示できます。

コレクションのstats()メソッド実行結果(抜粋)
> db.(コレクション名).stats()
{
        "ns" : "sample-db.collection01",
        "count" : 8031,
        "size" : 1447258112,
        "totalIndexSize" : 408800,
        (略)
}

実行中のクエリの情報取得(currentOp()メソッド)

currentOp()メソッドは、そのデータベースで実行中のオペレーションを表示できます。

currentOp()メソッド実行結果(抜粋)
> db.currentOp();
{
        "inprog" : [
                {
                        "opid" : 22991,
                        "op" : "insert",
                        "ns" : "sample-db.test",
                        "lockStats" : {
                                "timeLockedMicros" : {
                                        "r" : NumberLong(0),
                                        "w" : NumberLong(138) ←書き込みロックが138ms
                                },
                        (略)

上記の出力結果では、insertにおいて、書き込みロックが138ミリ秒発生していることがわかります。

詳細な使い方

この章で紹介したコマンドやメソッドの詳細な使い方は、以下の公式HPへのリンクを参照してください。

CUI以外の監視方法

RESTインターフェースからmongodの状態を表示

MongoDBのRESTインターフェースにブラウザでアクセスすることにより、mongostatと同じような情報を確認することもできます。MongoDBのRESTインターフェースは「⁠⁠MongoDBの起動ポート)+1000」番のポートで待ち受けていますので、ブラウザでそのポートにアクセスすると以下のような画面が表示できます。

図1 RESTインターフェースの画面
図1 RESTインターフェースの画面

また、⁠--rest」のオプションをつけることで、さらに豊富な情報をRESTインターフェースから取得することができます。

外部のモニタリングアプリケーションとの連携

MongoDBではNagiosMuninといった外部のモニタリングアプリケーションと連携できます。これらはどちらもオープンソースのプラグインを導入することで連携できます。

また、プラグインが開発されていない場合でも、serverStatusメソッドなどの出力をRESTインターフェースを通して自前のモニタリングアプリケーションに連携してやることにより、比較的簡単にプラグインを作ることができます。

さらに、有償版のMongoDB EnterpriseではSNMPプロトコルをサポートしており、SNMPを通してモニタリングアプリケーションと連携することも簡単にできます。

MMS(MongoDB Monitoring Service)

MongoDBの開発元である10gen社のサービスで、手元のMongoDBとインターネットにあるMMS(MongoDB Monitoring Service)を接続することにより、インターネットにあるMMSのWebページからMongoDBの監視をすることができます。詳しくは公式サイトをご参照ください。

監視すべき項目

では、今まで紹介した監視機能・ツールを用いて何を監視すべきかを簡単に解説したいと思います。これらはすべて一般論ですので、実運用をする場合は皆さんのシステムの特性を加味した上で監視項目を決めてください。

データ容量

最も基本的なことですが、データの量を監視し、ディスク溢れを未然に防ぐことが重要です。データ量を監視する場合は、db.stats()メソッドを用いてもよいですし、単純にOSのdfコマンドなどでもよいでしょう。注意点として、MongoDBでは格納するデータのサイズと実際にディスクを使用する容量には差があります。また、インデックスもそれなりにデータ容量がある場合があるので、忘れてはいけません。

メモリ使用量

MongoDBはデータファイルをメモリにのせますが、物理メモリにデータが乗り切りない場合、ディスクへのI/O(ページフォルト)が発生し性能劣化を引き起こします。そのため、MongoDBが利用するメモリ容量が物理メモリ量を上回らないように監視することが重要です。物理メモリ使用量の監視にはmongostatのresの部分や、serverStatus()のmem.residentの部分を見るのがよいでしょう。

トラフィック

MongoDBに対するクエリの数を常に監視することにより、性能劣化の原因が一時的な高負荷によるものなのか、そうではなく慢性的なリソース不足なのか判断することができます。トラフィックの監視ではqueryやinsertといったオペレーションの頻度、接続しているクライアントの数、およびネットワークの流量に注意しましよう。監視するには、mongotopやserverStatus()の出力結果を見るのがよいでしょう。

ロック時間

MongoDBは書き込み時の一貫性を保つためにデータをロックをしますが、ロックの時間が長いとその他のクエリがロックの解除を待つことになり、性能劣化を引き起こします。ロックにかかっている時間やロックを待っているクエリの数を監視することにより、性能劣化の原因がロック待ちかどうかを判断することができます。監視するのはserverStatus()のglobalLockを見るか、mongostatのlockedの値を見るのがよいでしょう。

スロウクエリ量

MongoDBでは、ある閾値以上に時間がかかったクエリをログファイルに記録します。性能要件に従って適切な閾値を設定することにより、性能要件を満たしていないクエリがどれだけあるか監視することができます。スロウクエリ監視をするには、ログファイルを監視します。

その他

最後に、MongoDBとは直接関係ありませんが、ディスクIOの性能を監視することも重要です。性能劣化の原因がMongoDBではなく、実はディスクが遅かったということもあります。監視するにはiostat等のOSのコマンドを利用しましょう。また、あまり問題になることはありませんが、CPU使用率も監視しておくとよいでしょう。

まとめと次回のテーマ

今回はMongoDBの監視機能の紹介と、それを用いてどのように監視すべきかを解説しました。この記事が、皆さんのMognoDBの障害軽減に役立てれば嬉しいです。

次回は、MongoDBの性能について紹介する予定です。お楽しみに!

おすすめ記事

記事・ニュース一覧