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

アーカイブの一覧に戻る

Kouhei Sutou kou****@clear*****
2014年 11月 26日 (水) 11:09:20 JST


須藤です。

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 メーリングリストの案内
アーカイブの一覧に戻る