中年engineerの独り言 - crumbjp

LinuxとApacheの憂鬱

MongoDB3.2 ReleaseNote所感

そろそろ3.2も手を付けようと思うので、検証がてらつらつらと。。

リリースノート

https://docs.mongodb.org/manual/release-notes/3.2/

非常に丁寧な日本語訳があるので、こちらもどうぞ
http://qiita.com/fetaro/items/cd570d70623b58b5deef

WiredTiger as Default

まあ規定路線なので、特に気にする必要なし。

Replication Election Enhancements

Primaryが落ちた時の検知が早くなった。
どういうシチュエーションでどの位早くなるのかはまだ検証してない。
少なくとも今迄の落ち認定10秒をカスタマイズ可能になった。
その他色々timeout値が弄れるようになった様だが、これはまだ実験段階なんだろう。と読む事もできる。
要注目

Sharded Cluster Enhancements

configサーバが独自2-phase-commit ではなく、普通のReplicaSet で組めるようになった。
今迄は3ノード限定。1ノードでも落ちたら(shard周りの)更新不能だったが、可用性が格段に上がったということだ。

readConcern

書き込み時の保証であるwriteConcernだけでなく、読み込み時の保証が取れるようになった。
ただ、こんな事をしてどうやって性能を上げるつもりなのか解らない
これはコードを読む必要がありそう。

Partial Indexes

全ドキュメントにインデックスを張らない随分とチャレンジングな機能。
正にドキュメントベース独特の悩みの具現化だな。
これは機能としては素晴らしいがアプリ側がかなり大変そうな気がする。
限定した使い方なら非常によさそう。

例えば、{ active: true } のドキュメントだけ indexに含める。
といった使い方が良い。
この様なケースならば、Oracleのbitmap indexより効率的かもしれない。

Document Validation

謎機能!!
ドキュメントベースのDBでこれをやるか!!
只でさえフィールドがnull、undefinedで、クエリー周りの混乱があるのにこういう事すると更に拍車をかけそう。
沢山失敗例がネットに溢れると思われる

Aggregation Framework Enhancements

色々足されているが、 まずは$lookupだけ気にしていれば良い。
他は細々しているが

  • 演算系のオペレータは嬉しい。
  • $unwind が配列以外を受け付けなくなったのがちょっと痛い
  • covered indexが有効になったので軽くなるケースも若干ある。(むしろ$lookupで有効ならば非常に嬉しい機能)
MongoDB Tools Enhancements

mongodump / mongorestore が圧縮転送可能になったので、ありがちな、mongodump & s3 に放り込む。といったバックアップが早くなるのが嬉しい。

Text Search Enhancements

例によって無視

New Storage Engines

気にする必要なし

General Enhancements

ビット演算オペレータは使えるケースがあるかな?無いよな・・・
ドキュメントベース使っててフィールド分けない理由が無いんだけど・・・

SpiderMonkey JavaScript Engine

なぜだ!!

WiredTiger and fsyncLock

以前にも触れたが、やっとまともにバックアップが取れるようになる。


あとは良いや。

3.2は新バージョンというより3.0 系の決定版のような位置づけっぽいですね。

MongoDB3.2 readConcernの挙動について

実装

mongosの場合はもうちょっと複雑になるが、レプリカセットの場合はこの辺に実装があるようだ

=== /db/repl/replication_coordinator_impl.cpp ===
    auto loopCondition = [this, isMajorityReadConcern, targetOpTime] {
        return isMajorityReadConcern
            ? !_currentCommittedSnapshot || targetOpTime > _currentCommittedSnapshot->opTime
            : targetOpTime > _getMyLastOptime_inlock();
    };

    while (loopCondition()) {
        Status interruptedStatus = txn->checkForInterruptNoAssert();
        if (!interruptedStatus.isOK()) {
            return ReadConcernResponse(interruptedStatus, Milliseconds(timer.millis()));
        }

        if (_inShutdown) {
            return ReadConcernResponse(Status(ErrorCodes::ShutdownInProgress, "shutting down"),
                                       Milliseconds(timer.millis()));
        }

        stdx::condition_variable condVar;
        WriteConcernOptions writeConcern;
        writeConcern.wMode = WriteConcernOptions::kMajority;

        WaiterInfo waitInfo(isMajorityReadConcern ? &_replicationWaiterList : &_opTimeWaiterList,
                            txn->getOpID(),
                            &targetOpTime,
                            isMajorityReadConcern ? &writeConcern : nullptr,
                            &condVar);

        if (CurOp::get(txn)->isMaxTimeSet()) {
            condVar.wait_for(lock, Microseconds(txn->getRemainingMaxTimeMicros()));
        } else {
            condVar.wait(lock);
        }
    }

どうもmajorityになるまで単純にwhile ループで待ってるようだが
こんな乱暴な事をすると、簡単にDOSになりそうだが、どうなんだろう?

仮に 1秒位遅延が起きた時に、5000 queryも readConcern: majority でクエリーすると何が起きるか?
余裕でリクエストを処理するスレッドを潰されてしまいそうな気がする。

だれか一緒に検証してくれる人いませんかね??