Kouhei Sutou
kou****@clear*****
2014年 12月 3日 (水) 21:10:26 JST
須藤です。 森さん、この件、Groongaだけで再現する方法を確立したのでちょっ と見てもらえませんか? 方法: % wget http://packages.groonga.org/tmp/data.tar.gz % tar xvf data.tar.gz % gdb --args groonga data/mroonga.mrn delete product_search F3110101671415148346 ... (gdb) b ii.c:2599 ← masterな前提 ... Breakpoint 1, chunk_merge (ctx=0x7fffffffdf70, ii=0x7e82e0, sb=0x7fffe7fd3000, bt=0x7fffe7f935e0, cinfo=0x7df090, rid=1713056, dv=0x7fffffff20b0, nextbp=0x7fffffff204e, sbpp=0x7fffffff2118, bidp=0x7fffffff1ff0, balance=0x7fffffff2048) at ii.c:2599 2599 if (!(rc = chunk_flush(ctx, ii, cinfo, enc, encsize))) { (gdb) p encsize $1 = 0 ↑でencsizeが0になっているんですが、これは正常なケースなのか どうかを確認して欲しいです。 もし、正常なケースなら0になったときの処理を追加するという対 応が妥当だと思います。 もし、異常なケースならそもそも0にならないようにどこかにチェッ クを入れるのが妥当だと思います。 私の予想は正常なケースじゃないかと思います。これ、マージしよ うとしたチャンクから何もマージする必要がなかったケースなんじゃ ないかと思うんですよねぇ。なので、このマージしようとしたチャ ンクをキレイにして再利用(?)できればいいんじゃないかなぁと 思いました。 In <20141****@clear*****> "[groonga-dev,02979] Re: delete後にselectするとmysqlが再起動する" on Wed, 26 Nov 2014 11:09:20 +0900 (JST), Kouhei Sutou <kou****@clear*****> wrote: > 須藤です。 > > In <CAA3x****@mail*****> > "[groonga-dev,02971] Re: delete後にselectするとmysqlが再起動する" on Tue, 25 Nov 2014 11:58:04 +0900, > saki kashi <saki.****@gmail*****> wrote: > >> https://github.com/kashihara3/mroonga >> こちらに配置させていただきました。 > > 確認しました。どちらも再現しました。 > >> falldown->当初の落ちる現象のデータです。 > > これですが、込み入っているので今回のリリースに修正を入れるの > は難しいです。来月リリースまでに修正します。 > > 以下、メモです。あまり気にしないでください。 > > 問題は2つあります。 > > 1. インデックスからエントリーを削除するところがバグっている > 2. ↑が失敗したときのエラーを無視しているので、エラーになっ > た時点で処理を中止せずに、何度も↑の処理を実行してしまっ > ている > > 1.は > > grn_ii_delete_one() -> > buffer_flush() -> > buffer_merge() -> > chunk_merge() > > で > > https://github.com/groonga/groonga/blob/master/lib/ii.c#l2567 > > ndf = ridp - dv[0].data; > > のndfが0になっているのがおかしい(あるいは、ndfが0になっても > いいけど0になったときを考慮していない)っぽいです。 > > ndfが0になるとその後でdv[0].data_sizeが0になってしまって、 > > https://github.com/groonga/groonga/blob/master/lib/ii.c#l2594 > > encsize = grn_p_encv(ctx, dv, ii->n_elements, enc); > > のencsizeも0になって、次の行の > > https://github.com/groonga/groonga/blob/master/lib/ii.c#l2595 > > if (!(rc = chunk_flush(ctx, ii, cinfo, enc, encsize))) { > > がGRN_NO_MEMORY_AVAILABLEを返すので、結局grn_ii_delete_one() > が失敗しています。 > > (chunk_flushがGRN_NO_MEMORY_AVAILABLEを返すのはメモリーがな > いからではなくて、サイズが0のメモリー領域を割り当てられない > から。) > > Groonga単体で再現できる手順を作って、森さんに見てもらったほ > うがよさそうな気がしています。 > > > 2.は > > https://github.com/groonga/groonga/blob/master/lib/ii.c#L4854 > > とかのgrn_ii_delete_one()の戻り値をチェックして > grn_ii_update()がエラーを返すようにしないといけないです。 > こうしないと、何度もgrn_ii_delete_one()を呼び出して1.の状態 > になり、grn_ii_bufferがムダに増えていきます。 > > 今回、mmapできる量を増やしたら問題が発生しにくくなったのは、 > ムダなgrn_ii_bufferが増えても大丈夫なくらいにmmapできるよう > になったからです。1.を解決すれば必要な分だけgrn_ii_bufferを > 使うようになるので、根本解決をするには1.の対応が必要です。 > > >> REPLACE->リプレイスでエラーになるデータです。 > > これは、使い方にも問題がありました。 > > 最小の再現ケースは↓です。 > > CREATE TABLE test ( > id varchar(32) NOT NULL PRIMARY KEY, > content text, > FULLTEXT INDEX (content) > ) DEFAULT CHARSET=utf8mb4; > > REPLACE INTO test(content) VALUES("Hello"); > > ポイントは次の3点です。 > > * PRIMARY KEYがある > (AUTO_INCREMENTを指定しなくてデフォルト値はない) > * FULLTEXT INDEXがある > * REPLACE INTOでPRIMARY KEYを指定していない > > 主キーがないので本来はエラーにするべきなんですが、そこのチェッ > クが抜けていたので、Groongaの名前のエラーがでてしまっていま > した。 > > Mroongaレベルでちゃんとチェックをするようにしたので、今回の > リリースからはMySQLっぽいエラーが返ります。 > > 対策は、「REPLACE INTOするときに主キーも一緒に指定すること」 > です。 > > > 落ちるケースについての対応はもうしばらくお待ちください。 > > -- > 須藤 功平 <kou****@clear*****> > 株式会社クリアコード <http://www.clear-code.com/> > > Groongaベースの全文検索システムを総合サポート: > http://groonga.org/ja/support/ > 11/29 全文検索エンジンGroongaを囲む夕べ5: > http://groonga.doorkeeper.jp/events/15816 > 名著『リーダブルコード』を解説者と一緒に読み解こう: > http://schoo.jp/class/1502 > > _______________________________________________ > groonga-dev mailing list > groon****@lists***** > http://lists.sourceforge.jp/mailman/listinfo/groonga-dev