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