LoginSignup
2
2

More than 5 years have passed since last update.

全文検索エンジンGroongaで複数プロセスからアクセスするときの注意点

Last updated at Posted at 2016-09-16

[お知らせ] 2016年9月29日(肉の日)にMySQLとPostgreSQLと日本語全文検索3というイベントが開催されます。今回の事例紹介はMySQL InnoDBの全文検索機能です。Groongaをストレージエンジンとして採用しているMroongaの紹介もありますよ。

はじめに

高速な全文検索を実現するためのソフトウェアとして、Groongaがあります。この記事を書いている時点の最新バージョンは6.0.8です。

Groongaにアクセスするプロセスが1つのときには問題になりませんが、複数のプロセスからGroongaにアクセス(例えば複数のgroongaコマンドで同じデータベースを開く)するようになったときには、ちょっと注意しないといけないことがあります。

今回はその「ちょっと注意しないといけない」ポイントについて説明します。

スキーマを変更する場合

Groongaのデータベースは複数のプロセスで共有可能なようになっています。そのため複数のプロセスからデータを更新することに何ら問題はありません。
しかし、スキーマの変更となると事情が変わってきます。
例えば、同じGroongaのデータベースを複数のクライアントからアクセスしスキーマの変更を行うケースを考えます。

あらかじめ、以下のスキーマでデータベースを構築してあるとしましょう。

table_remove User

table_create User TABLE_PAT_KEY UInt32
column_create User first_name COLUMN_SCALAR ShortText
column_create User last_name COLUMN_SCALAR ShortText

load --table User
[
{"_key":1, "first_name":"Taro", "last_name":"Maruwa"},
{"_key":2, "first_name":"Hanako", "last_name":"Yamada"}
]

groongaコマンドを使って、データベースにアクセスすることにします。
プロセスAでは、スキーマの変更はしません。一方プロセスBではスキーマを変更するものとします。

プロセスA

プロセスAではスキーマを変更しません。定義されているテーブルとカラムのリストを確認してみましょう。
table_listcolumn_listで定義を確認します。

% groonga testdb/db
> table_list 
[[0,1474006053.211516,0.0006153583526611328],[[["id","UInt32"],["name","ShortText"],["path","ShortText"],["flags","ShortText"],["domain","ShortText"],["range","ShortText"],["default_tokenizer","ShortText"],["normalizer","ShortText"]],[256,"User","testdb/db.0000100","TABLE_PAT_KEY|PERSISTENT","UInt32",null,null,null]]]
> column_list User
[[0,1474006056.986597,0.0002224445343017578],[[["id","UInt32"],["name","ShortText"],["path","ShortText"],["type","ShortText"],["flags","ShortText"],["domain","ShortText"],["range","ShortText"],["source","ShortText"]],[256,"_key","","","COLUMN_SCALAR","User","UInt32",[]],[258,"first_name","testdb/db.0000102","var","COLUMN_SCALAR|PERSISTENT","User","ShortText",[]],[257,"last_name","testdb/db.0000101","var","COLUMN_SCALAR|PERSISTENT","User","ShortText",[]]]]

プロセスB

プロセスBではスキーマの定義を変更します。
具体的には、last_nameのカラムの型をShortTextからLongTextに変更します。そのために、一旦Userテーブルからlast_nameカラムを削除して、再度カラムを作りなおします。

% groonga testdb/db
> column_remove User last_name
[[0,1474006068.331246,0.002974987030029297],true]
> column_create User last_name COLUMN_SCALAR LongText
[[0,1474007443.677316,0.004316091537475586],true]
> column_list User
[[0,1474007451.995359,8.463859558105469e-05],[[["id","UInt32"],["name","ShortText"],["path","ShortText"],["type","ShortText"],["flags","ShortText"],["domain","ShortText"],["range","ShortText"],["source","ShortText"]],[256,"_key","","","COLUMN_SCALAR","User","UInt32",[]],[258,"first_name","testdb/db.0000102","var","COLUMN_SCALAR|PERSISTENT","User","ShortText",[]],[257,"last_name","testdb/db.0000101","var","COLUMN_SCALAR|PERSISTENT","User","LongText",[]]]]

column_listで現在のカラムを参照すると、last_nameカラムの型がLongTextに変更されていることがわかります。

[257,"last_name","testdb/db.0000101","var","COLUMN_SCALAR|PERSISTENT","User","LongText",[]]

再びプロセスA

さて、プロセスAではプロセスBのスキーマ定義変更はどのように見えているでしょうか。
プロセスAに戻って確認してみましょう。

プロセスBがテーブルを削除した時点では、カラムが消えているだけなので特に問題がありません。

> column_list User
[[0,1474006125.018618,9.870529174804688e-05],[[["id","UInt32"],["name","ShortText"],["path","ShortText"],["type","ShortText"],["flags","ShortText"],["domain","ShortText"],["range","ShortText"],["source","ShortText"]],[256,"_key","","","COLUMN_SCALAR","User","UInt32",[]],[258,"first_name","testdb/db.0000102","var","COLUMN_SCALAR|PERSISTENT","User","ShortText",[]]]]

しかし、カラムが再作成されたあとはどうでしょうか。column_listで定義を確認してみます。

> column_list User
[[0,1474007459.899354,9.703636169433594e-05],[[["id","UInt32"],["name","ShortText"],["path","ShortText"],["type","ShortText"],["flags","ShortText"],["domain","ShortText"],["range","ShortText"],["source","ShortText"]],[256,"_key","","","COLUMN_SCALAR","User","UInt32",[]],[258,"first_name","testdb/db.0000102","var","COLUMN_SCALAR|PERSISTENT","User","ShortText",[]],[257,"last_name","testdb/db.0000101","var","COLUMN_SCALAR|PERSISTENT","User","ShortText",[]]]]

注目すべきは、last_nameの型です。プロセスBでLongText型で作成したはずのlast_nameカラムが、何故かShortText型になってしまっています。これでは、プロセスBでカラムを再作成する前の状態ですね。

[257,"last_name","testdb/db.0000101","var","COLUMN_SCALAR|PERSISTENT","User","ShortText",[]]

古いlast_nameの定義を参照したままになってしまっていることがわかりました。

古い定義が参照されたままになる問題への対策

古い定義を参照したままになっているのが問題なので、再度データベースを開き直します。
具体的にはプロセスAを実行しているgroongaコマンドを一旦終了します。

> quit
[[0,1474010060.188753,3.24249267578125e-05],true]
% groonga testdb/db
> column_list User
[[0,1474010067.628873,0.0002775192260742188],[[["id","UInt32"],["name","ShortText"],["path","ShortText"],["type","ShortText"],["flags","ShortText"],["domain","ShortText"],["range","ShortText"],["source","ShortText"]],[256,"_key","","","COLUMN_SCALAR","User","UInt32",[]],[258,"first_name","testdb/db.0000102","var","COLUMN_SCALAR|PERSISTENT","User","ShortText",[]],[257,"last_name","testdb/db.0000101","var","COLUMN_SCALAR|PERSISTENT","User","LongText",[]]]]

再度データベースを開き直したので、期待通りにlast_nameカラムはLongText型になっています。

[257,"last_name","testdb/db.0000101","var","COLUMN_SCALAR|PERSISTENT","User","LongText",[]]

groongaコマンドを終了したくない場合には、database_unmapコマンドを実行する方法もあります。
このコマンドを実行すると、それまでキャッシュされた情報を一旦破棄するからです。

まとめ

groongaコマンドを利用して複数のプロセスからGroongaにアクセスするときに、スキーマの変更を伴う場合に注意するべきポイントを説明しました。
変更したスキーマ定義が反映されていないときには、複数のプロセスでアクセスしたりしていないか確認してみてください。
もし、上記の状況になったら、groongaコマンドを一旦終了するか、database_unmapコマンドを実行するなどしてデータベースを開き直すことで解決できます。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2