[groonga-dev,03002] Re: delete後にselectするとmysqlが再起動する

アーカイブの一覧に戻る

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




groonga-dev メーリングリストの案内
アーカイブの一覧に戻る