Memo/MongoDB

https://dexlab.net:443/pukiwiki/index.php?Memo/MongoDB
 

MongoDB

MongoDBは、オープンソースソフトウェアのドキュメント指向データベースである。C++言語で記述されており、開発とサポートはMongoDB Inc.によって行なわれている。
  • 各OS向けにバイナリが配布されている。RHEL/CentOS 6/7向けあり
  • docs:

トラブルシューティング


No electable secondaries caught up as of ...

  • rs.stepDown()が失敗する
    rs0:PRIMARY> rs.stepDown()
    
    {
            "ok" : 0,
            "errmsg" : "No electable secondaries caught up as of 2021-01-02T03:04:00.000+0000",
            "code" : 50
    }
  • replSetStepDown — MongoDB Manual
    • force: true レプリケーション・ラグのあるセカンダリが新しいプライマリになった場合、ロールバックが発生する可能性があり
      # force: falseで試す
      db.adminCommand( { replSetStepDown: 120, secondaryCatchUpPeriodSecs: 15, force: false } )
      
      # force: trueで試す。rs.status()で確認すると、成功はするがSECONDARYが2つになっていた
      db.adminCommand( { replSetStepDown: 120, secondaryCatchUpPeriodSecs: 15, force: true } )
  • SECONDARYが二つになってしまった場合、mongodを再起動する事でPRIMARYへ戻る時があった
    sudo service mongod restart

監視

  • mongostat
    • バージョンによって項目が増加するので、awkではなくjqで項目名を指定したほうが良さそう
    • v3.4以降は「-o 項目」「--humanReadable false」等便利なオプションがある。v3.4未満では、表記が文字列強制(--humanReadable true)なためプログラムから解析するのが難しい。
    • 省略ヘッダ文字列 https://github.com/mongodb/mongo-tools/blob/master/mongostat/stat_consumer/line/stat_headers.go#L35
    • mongostat v3.0:
      mongostat -n 1
      insert query update delete getmore command flushes vsize  res qr|qw ar|aw netIn netOut conn             set repl     time
          *0    *0     *0     *0       0     1|0       0  2.1G 1.3G   0|0   0|0   79b    13k    7            rs01  SEC 07:04:46
      
      # awkでconnを抽出
      mongostat -n 1 --noheaders | awk '{print $14;}'
      7
      
      # jsonで出力
      mongostat -n 1 --json
      
      {"host1":{"command":"10|0","conn":"26","delete":"*0","getmore":"8","host":"host1","insert":"*0","netIn":"11k","netOut":"24k","query":"4","repl":"PRI","res":"1.5G","set":"rs01","time":"03:54:30","update":"19","vsize":"3.9G"}}
      
      
      # jqで.connだけ出力
      mongostat -n 1 --json | jq -r '.[].conn'
  • db.serverStatus() 詳細なステータス
    • JSON.stringify() だと 標準JSONなのでjq等で扱い安い
      mongo --quiet --eval 'JSON.stringify(db.serverStatus())'
      
      mongo --quiet --eval 'JSON.stringify(db.serverStatus().network)'
      {"bytesIn":{"floatApprox":382313310},"bytesOut":{"floatApprox":834527308},"numRequests":{"floatApprox":2539018}}
      
      mongo --quiet --eval 'JSON.stringify(db.serverStatus().network.bytesIn.floatApprox)'
      382279847
    • printjson()だと値がNumberLong(value) なので、外部プログラムからは扱いにくい
      mongo --quiet --eval 'printjson(db.serverStatus())'
      
      {
              "host" : "host1",
              "version" : "3.0.x-1.4",
              "process" : "mongod",
      ...
              "connections" : {
                      "current" : 7,
                      "available" : 51174,
                      "totalCreated" : NumberLong(3304436)
              },
      ...
      
      # .networkの例 
      mongo --quiet --eval 'printjson(db.serverStatus().network)'
      {
              "bytesIn" : NumberLong(382298771),
              "bytesOut" : NumberLong(834471201),
              "numRequests" : NumberLong(2538920)
      }
      
      mongo --quiet --eval 'printjson(db.serverStatus().network.bytesIn)'
      NumberLong(382330737)
      
      mongo --quiet --eval 'printjson(db.serverStatus().network.bytesIn.floatApprox)'
      382330737
      
      
      # connections.current だけ抽出
      mongo --quiet --eval 'printjson(db.serverStatus().connections.current)'
      
      # mem.resident だけ抽出
      mongo --quiet --eval 'printjson(db.serverStatus().mem.resident)'

レプリケーション状態の判別

  • PRIMARYホスト上で実行した場合
    mongo --quiet --eval "printjson(db.isMaster().ismaster)"
    true
    
    mongo --quiet --eval "printjson(db.isMaster().secondary)"
    false
    
    # myState: 1=PRIMARY, 2=SECONDARY, 7=ARBITER
    mongo --quiet --eval "printjson(rs.status().myState)"
    1

パフォーマンスチューニング

  • モニタリング
    mongo --quiet --eval "printjson(db.serverStatus())"

現在のパラメータ取得

  • 全パラメータをjson型式で表示
    mongo --quiet --eval "printjson(db.adminCommand( { getParameter : '*' } ))"

メモリ使用量の上限を設定

エンジンによって設定が異なる。出来ない事もあるようだ。

現在のメモリ使用量:

mongo --quiet --eval "printjson(db.serverStatus().mem)"

wiredTiger

PERCONA rocksdb:


データサイズ削減

mongodbからコレクションを消しても、OSから見た空きディスク容量は増えない。

  • 単一collectionに対して実行。通常はSECONDARYに対して実行する。PRIMARYに対して実行する場合は、「, force: true」を付ける。PRIMARYがロックされて、他の操作を受け付けなくなる。
    mongo --quiet --eval "printjson(db.runCommand( { compact: '<collection name>'} ))" <db name>
  • mongodb v2.6
    • capped collectionは非対応だった
      { "ok" : 0, "errmsg" : "cannot compact a capped collection" }
  • レプリケーションの場合、データを消して、再同期でサイズが減る。capped collectionも同様に減る。データ量にもよるが、〜数時間かかる事も。ARBITER以外のホストで実行する必要がある。
    MONGODB_PATH=/var/lib/mongo
    
    mongo --quiet --eval 'printjson(rs.stepDown())'
    
    # "stateStr" : "SECONDARY" に変わるまで待つ
    mongo --quiet --eval 'printjson(rs.status())'
    
    # monitを使っている場合は無効に
    sudo monit unmonitor mongod
    
    sudo service mongod stop
    # 既存データをバックアップ。ただし、再同期に溢れる場合もあるので、空き容量が使用量の2倍以下の場合、消した方が良い事も。
    sudo mv $MONGODB_PATH ${MONGODB_PATH}.$(date +%Y%m%d)
    sudo mkdir $MONGODB_PATH
    sudo chown mongod:mongod $MONGODB_PATH
    sudo service mongod start
    
    # monitを使っている場合は有効に
    sudo monit monitor mongod
    
    # 使用しているDB名でファイルができている事を確認
    ls -lh $MONGODB_PATH
    
    # "stateStr" : "SECONDARY" に変わるまで待つ。データ量によっては〜数時間かかる。
    mongo --quiet --eval 'printjson(rs.status())'
    
    # 古いDBファイルを削除
    sudo rm -rf /var/lib/mongo.YYYYMMDD

古いバージョンのダウンロード


db.serverStatus(): 現在の設定を確認

# memだけ
mongo --quiet --eval 'printjson(db.serverStatus().mem)'

# connectionsだけ
mongo --quiet --eval "printjson(db.serverStatus().connections)"

バックアップ&リストア

  • dumpはディレクトリが出来る
    sudo service mongod stop
    
    sudo mongodump -v --dbpath /var/lib/mongo --out ./mongo_dump
  • restore: datapathは空ディレクトリで良い
    sudo /var/lib/mongo /var/lib/mongo.$(date +%Y%m%d)
    sudo mkdir -p /var/lib/mongo
    sudo chown mongod:mongod /var/lib/mongo
    
    sudo service mongod start
    
    mongorestore -v ./mongo_dump

Capped Collections: コレクションの上限サイズを指定する

  • Capped Collections — MongoDB Manual
    • コレクションサイズが増えると、クエリがタイムアウト/ディスクが溢れる場合があるので、上限を決めたい時などに便利
  • createCollection: 新規collection作成時に上限を設定する。
    • 「test01」collectionの上限サイズを「8MB」に設定。
      mongo sample --quiet --eval 'printjson(db.createCollection("test01", { capped: true, size: 8*1024*1024}))'
  • convertToCapped: 既存collectionをcappedへ変更
    • convertToCapped — MongoDB Manual
    • 作業中はロックされる。大きいcollectionはロック時間が長くなるため注意。
    • cappedが未設定のコレクションを探す
      mongo --quiet --eval 'db.getCollectionNames().forEach(function(n){print(n + "," + db[n].stats().capped)})' sample | grep -v -E '^system|,true$' > ./mongo.capped.txt
    • MB単位でコレクションサイズを表示
      for app_id in $(cut -d, -f 1 mongo.capped.txt); do \
      echo -n "$app_id," >> ./mongo.size.txt; \
      mongo --quiet --eval "printjson(db.${app_id}.stats(1024*1024).size)" sample >> ./mongo.size.txt; \
      done
      
      grep -v ',0$' mongo.size.txt
    • 「test01」collectionの上限サイズを「8MB」に設定
      mongo --quiet --eval 'printjson(db.runCommand({ convertToCapped: "test01", size: 8*1024*1024}))' sample
    • 複数のコレクションを対象とする場合
      for app_id in $(cut -d, -f 1 mongo.capped.txt); do \
      echo -n "$app_id,"; \
      mongo --quiet --eval "printjson(db.runCommand({ convertToCapped: '${app_id}', size: 8*1024*1024}))" sample
      done
  • 確認: maxは最大要素数
    mongo --quiet --eval 'printjson(db.test01.stats(1024*1024))' sample
  • cappedが無効なコレクション表示
    mongo --quiet --eval 'db.getCollectionNames().forEach(function(n){print(n + "," + db[n].stats().capped)})' sample| grep -v -E '^system|,true$'

mongodサービス起動時のtimeoutを延長する

データが多くなってくるとでデフォルトの90秒では起動しない事がある。

  • CentOS 7 64bit
  • mongodのTimeoutStartSecを90秒から3分に伸ばす
    sudo vim /etc/systemd/system/mongod.service.d/timeout.conf
    --
    [Service]
    TimeoutStartSec=3m
    --
    
    sudo systemctl daemon-reload
    systemctl show mongod -p TimeoutStartUSec
    TimeoutStartUSec=3min
  • TimeoutStartSec="3m" のようにダブルクオーテーションで括ると認識せず、デフォルトの値に戻ってしまう。特にエラーもでない

レプリケーション


mongoコマンド

  • JSON形式としては無効な出力になる
    • 例:
      date" : ISODate("2020-05-01T01:03:04.317Z")
  • printjsononeline(): スペースを含まないjsonで表示。
  • サーバ統計情報
    mongo --quiet --eval 'printjson(db.serverStatus())'
  • レプリケーション情報
    mongo --quiet --eval 'printjson(rs.status())'
  • コネクションプール情報を表示
    mongo --quiet --eval 'printjson(db.runCommand( { "connPoolStats" : 1 } ))'
  • hostとdbを指定してコマンド実行
    mongo --quiet --host localhost --eval 'db.col.count()' sample
  • mongodに接続
    mongo
  • DB一覧
    show dbs
  • DB切替
    use <db name>
  • collection一覧
    show collections
  • 「test01」collectionの情報表示。サイズをMBで。
    db.test01.stats(1024*1024)
  • コレクション毎のストレージサイズをMB単位で表示
    db.getCollectionNames().forEach(function(n){print(n + "," + db[n].stats().storageSize/1024/1024 + " MB")})
  • コレクション毎の要素数を表示
    db.getCollectionNames().forEach(function(n){print(n + "," + db[n].count())})
  • コレクション毎のIndexを表示
    db.getCollectionNames().forEach(function(n){print(n); printjson(db[n].getIndexes())});

Max open files/Max processesの設定

  • RHEL/CentOS 6/7のデフォルトでは1024と低いため、最大値を上げる必要がある
    sudo cat /proc/$(pidof mongod)/limits | grep -P "open|proc"
    Max processes             1024                 64000                processes
    Max open files            1024                 4096                 files
  • initd (RHEL/CentOS 6), systemd(RHEL/CentOS 7)で設定箇所が異なるので注意
  • RHEL/CentOS 7: systemdの場合
    sudo mkdir /etc/systemd/system/mongod.service.d
    sudo vim /etc/systemd/system/mongod.service.d/limits.conf
    --
    # https://docs.mongodb.com/manual/reference/ulimit/ 
    #
    # The settings is what mongoDB officially recommends.
    #
    [Service]
    # Other directives omitted
    # (file size)
    LimitFSIZE=infinity
    # (cpu time)
    LimitCPU=infinity
    # (virtual memory size)
    LimitAS=infinity
    # (open files)
    LimitNOFILE=64000
    # (processes/threads)
    LimitNPROC=64000
    --
    sudo systemctl daemon-reload
    sudo service mongod restart
  • RHEL/CentOS 6: initdの場合
    sudo vim /etc/security/limits.d/99-mongodb-nproc.conf
    --
    # http://docs.mongodb.org/manual/reference/ulimit/
    mongod          soft    nproc     64000
    mongod          soft    nofile    64000
    --
    sudo service mongod restart

TLS/SSL接続

  • 記事

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2021-04-19 (月) 18:56:46 (48m)