Home » October 2005 » MT 3.2でrecently_commented_onとBerkeleyDBに嵌っている人が多い件について

MT 3.2でrecently_commented_onとBerkeleyDBに嵌っている人が多い件について

MT 3.2日本語版がリリースされてすでにインストールしている人も多いかと思いますが、嵌っている人も多いようです。代表的には以下の二種類の嵌り方をしている人が多いみたいです。

  1. 小粋空間: 3.2-ja 再構築時のパフォーマンス
  2. ちはろぐ: 「Movable Type 3.2 日本語版の提供を開始」らしいけど……(2005年09月29日)

このエントリーはこの2つの問題に対して解答を与えるためのものです。

念のため、BerkeleyDBをObjectDriverに使うくらいなら最初からSQLiteを使った方がずっと幸せになれる(というかまだBerkeleyDBを使ってたのか、捨てちまえ)とご忠告申し上げます。

recently_commented_onに関わる問題

あまり言及されていませんが、MT 3.1以前と3.2ではrecently_commented_onの仕様が異なっています(ソースコードが「公開された仕様」であると信じるならば)。

注: さらにMT 3.2-ja-2では、BerkeleyDB, SQLite, MySQLでは従来とおり、Postgresではここに書いたとおりの振る舞いをするように変更されています。訳が分かりませんが、前者の3つのDBエンジンを使用している場合には、recently_commented_onをlastn, daysオプションを一緒に指定すると無視されるので気をつけましょう。

3.1以前では、recently_commented_onはlastnやdaysオプションと一緒に指定することはできませんでしたが、3.2ではできます。つまり、以前はすべてのエントリーを対象に最近コメントされたエントリーをリストアップする機能でしたが、3.2では指定された範囲のエントリーを対象に最近コメントされたエントリーをリストアップする機能となりました。

多少機能が強化されたわけですが、メモリの消費量と速度に影響があります。具体的には指定された範囲のMT::Entryオブジェクトをすべてメモリ上に読み込んだ後、それら個々のエントリーに付けられた最終コメント時刻の降順にソートし、recently_commented_onオプションで指定した数だけ先頭から取り出すということを行います。lastnなどで範囲指定することなく使用すると、上記の操作がすべてのエントリーを対象に行われることになります。したがって、なるべくlastn, daysと併用するようにすることです。

また、これとは別にMT::Entry->comment_latestでやたらメモリを消費するという、BerkeleyDB特有の問題もあります。いかにも循環参照とか起きていそうで嫌な感じです。後で述べるパッチではこの問題を「回避」するコード修正を含みます。この修正によって(recently_commented_onに関しては)ほぼ許容可能なメモリ消費と速度で動作するはずです。

BerkeleyDBを使っていてMTEntryNextなどが正常に動作しない問題

日本語版β2でなされた変更で、「同日時のエントリーが複数あった場合に、エントリーの編集画面で『前のエントリー/次のエントリー』が正しく動作しない」という問題への修正がありました。これはつまり、同一日時のエントリーの順番をエントリーのIDを使って決める、という修正がなされたわけです。このこと自体はリーズナブルですね。

さて、同一日時のエントリーが4つあり、そのIDが1, 5, 9, 10だったとします。ID=5のエントリーの「次のエントリー」を決定するには、ID=5と同一時刻に作成された1, 9, 10のうち、5より大きい最小のものを選択することになります。逆に「前のエントリー」を決定するには5より小さい最大のものを選択することになります。このためには一般にエントリー群をIDに関してソートできなくてはなりません。

ところでMTのBerkeleyDB用のObjectDriverには古くからマイナーながら知られたバグがあって、対象オブジェクトをIDに関してソートして指定個数取り出すことができません(他のフィールドに関してソートすることはできる)。が、lib/MT/Entry.pmのsub _nextprevにはそのようなコードが記述されています。これではMTEntryPrevious/Nextや(同じロジックを用いる)エントリーの編集画面の『前のエントリー/次のエントリー』が正しく動作するはずがありません。

要するに、このバグを真っ当に修正するか何らかのwork aroundを用意する必要があります。実は同じ問題がlib/MT/Comment.pmとlib/MT/TBPing.pmにもあります。下で述べるパッチはwork aroundコードを挿入するものです。その後真っ当に修正する方法を思いついたのでパッチはそのように変更されています。

パッチ

説明はともかく以下のパッチを参照のこと。

dbm_flaw-comment_latest.patch

どうもパッチのあて方が分からないという人が多いみたいなので説明しておきます。
  1. Linux/FreeBSDなどではpatchコマンドがありますが、Windowsなどには標準では入っていません。Cygwinをインストールするなり、Programmers' toolboxからWindows版GNU Patchをゲットしておく必要があります。
  2. パッチファイルをMT 3.2日本語を展開したディレクトリに置きます。
  3. コマンドラインで「patch -p0 < パッチファイル名」と実行します。

2005-10-02 15:47追記: 以前のパッチにミスがありました。すでに適用した方は再度やり直してください。

2005-10-02 19:20追記: さらにrecently_commented_onを使用してもメモリ使用量が増大しないように対処しました。多分完璧です。

2005-10-03 16:06追記: たびたび申し訳ない。Entry.pm, Comment.pm, TBPing.pmに回避コードを入れるのは止めにして、DBM.pmを修正しました。この方が修正が圧倒的に少なくて済みます。

2005-10-04 00:35追記: さらに申し訳ない。MT 3.2ではDBからロードしたオブジェクトをキャッシュしておくようになっていて、それためメモリの使用量が3.1以前より大きくなっています。ところで、MySQLなどの場合にはこのキャッシュを一定個数以上作らないようにad hocなGarbage Collectionが行われるのに対し、BerkeleyDBの場合には作りっぱなしになっています。新しいパッチではMySQLなどと同様Garbage Collectionを行うように修正を加えています。

2005-10-05 11:40追記: 若干修正。Six Apartから何らかの正式な対策が用意される予定です(Six Apart - MovableType News: Berkeley DBの環境下でMovable Type 3.2日本語版をご利用のお客様へのお知らせ)。

このエントリーのトラックバックURL: http://as-is.net/mt/mt-tb.cgi/321

Links referred to this entry

Comments (9)

  1. (o)さ~ん(泣)

    辛口ながらありがとうございます。

    ちなみにうちが借りているサーバではDBD-SQLiteは2005/9/3に追加されたばかりので……これまで使えませんでした。
    http://www.sakura.ne.jp/news/20050905-003.news
    Sixapartのエントリーへのトラックバック元巡りをしてたと気に、同じサーバーでの下位プラインでMySQLを使えないプランなのにまともに動いていたMT32があったのはSQLiteを使ってたのか……

    これからパッチを試してきます。

  2. パッチの適用終わらせてきました。
    ばっちりでした。ありがとうございます。


    ……お世話になり過ぎですね……


    追伸:
    前のコメントの「プライン」→「プラン」でお願いします。

  3. すんません。前のパッチにちょっとミスがありました。

    if ($direction eq 'next') {
    というところを
    if ($direction eq 'ascend') {
    としないと同一時刻に作成されたエントリーが正しくハンドリングできません。

    パッチを当て直す方が簡単だと思いますけどね。

  4. パッチ、当て直しましたー
    ほんとに毎度毎度……

  5. もしかして2005-10-04 00:35版のパッチは、エントリーを公開状態で投稿/下書きから公開に変更で起きる再構築や、管理画面からの再構築の「インデックス/テンプレートを再構築する」でのメモリー消費量が、未パッチ状態や、2005-10-02 15:47版や2005-10-02 19:20版より増えてないでしょうか~(2005-10-03 16:06版は試せず)

    それらの状態での公開状態での投稿/下書きから公開での再構築が大丈夫だったのに、2005-10-04 00:35版からサーバーエラーで無理になってしまいました(緊急回避に一時的にデータベースをSQLiteに変換しました)


    手パッチなんでパッチ当てミスってこともかなりありえますが……そろそろ、diffを使えるようにしたほうが良いかなぁ……

  6. 一時的なメモリ消費量が増えている可能性は否定しません。しかし、ソフトウェアとしての良し悪しという点ではDBM.pmを修正する方がよいでしょう。ちなみに10/02時点のものは以下にあります。

    http://as-is.net/blog/archives/misc/mt32/dbm_flaw-comment_latest-1002.patch

    最後のエラーは心当たりがなくもないです。今日置き直したパッチは少しそのあたりを考慮しています。

  7. (o)さん、毎度お疲れ様です。

    2005-10-04 00:35版改と、http://as-is.net/blog/archives/misc/mt32/dbm_flaw-comment_latest-1002.patch で動作を比べてみました。

    2005-10-04 00:35版改では「インデックス・テンプレートの再構築」で徐々に使用メモリー量が増えていき500MBを超えたあたりでサーバーエラーで停止、dbm_flaw-comment_latest-1002.patchでは徐々に増えていくものの180MB程度で再構築成功でした。


    MT3.2日本語版に移行した後のエントリーが増えててMT3.171などに戻れない上で、BerkeleyDBから他のデータベースに移行する回避手段が無いヒトや、その移行処理を出来ない(mt-db2sql.cgiでサーバーエラーが出る。サーバーエラー回避の為にシェル上で実行するという手段が取れない。mt-db2sql.cgiを使用する場合のmt-config.cgiの設定がよく判らないなど)で、BerkeleyDBから逃げられない場合は 2005-10-04 00:35版改よりも dbm_flaw-comment_latest-1002.patch を使っておくほうが良いかもしれません。

    では~

  8. パッチに関してはいろいろ難しいところがありますね。Six Apartが動き始めているので、私はアドバイスはすれ、手出しはしないことにしました。

    mt-db-convert.cgiというのも作ってありますが、まだ3.2に対応させていません。
    http://as-is.net/blog/archives/001023.html

    これを使うとSQLiteへの変換がバカッパヤになり、500 Errorを見ることはありません。あと、mt-config.cgiを後で書き換えることになるので、BerkeleyDBに上書きしてしまうなどのありがちなミスを防げます。

  9. 初めまして。

    「念のため、BerkeleyDBをObjectDriverに使うくらいなら最初からSQLiteを使った方がずっと幸せになれる(というかまだBerkeleyDBを使ってたのか、捨てちまえ)とご忠告申し上げます。 」

    上記同感です。でも設定が簡単というのは捨てがたいのでしょうね。。。
    初心者の方には。そしてデータベースの移行がめんどくさい(わからない?)のだと思います。

Post a comment

Remember me?