Y-Ken Studio

新しもの好きのデータエンジニアが四方山話をお届けします。

groonga/mroongaの.mrnファイルがlock failedとなった場合の復旧方法

何らかの原因によりlock failedとなり、mroongaのテーブルを含むデータベースの
操作が出来なくなったときの復旧方法を紹介します。

これだけだと若干不親切なので、状況含めて説明します。

drop tableコマンドを発行した所、lock待ちとなる

mysql> show processlist;
+----+------+-----------+------+---------+------+-------------+------------------------+
| Id | User | Host      | db   | Command | Time | State       | Info                   |
+----+------+-----------+------+---------+------+-------------+------------------------+
|  1 | root | localhost | NULL | Query   |   15 | System lock | drop database wikipedia |
|  2 | root | localhost | NULL | Query   |    0 | init        | show processlist       |
+----+------+-----------+------+---------+------+-------------+------------------------+
2 rows in set (0.00 sec)

その後は、MySQLは起ち上がるものの、エラーが起きたそのデータベースに対して drop databaseも発行できない状態(System lockとなる)になります。

/var/lib/mysql/groonga.log

このファイルを見ると、確かにロック競合が起きていることが分かります。

$ sudo tail /var/lib/mysql/groonga.log
2013-05-08 19:10:01.010939|n|1d436700|io(wikipedia.mrn) collisions(1000/119): lock failed 1000 times
2013-05-08 19:28:58.470488|n|1d436700|io(wikipedia.mrn) collisions(1000000/119)

手動復旧方法

この状況になったら、手動復旧オペレーションが必要です。
ただ、このコマンドは状況によってはMySQLがinvalid pointerやSegmentation faultで落ちる可能性があります。
例えば全文検索インデックスが破損しているためにロックがかかった場合には、ロック解除しても再度そのテーブルへの更新が発生すればロックが掛かったまま落ちます。
本番稼働中のサーバでむやみに発行しないよう、気をつけましょう。

MySQLから行う場合

mroonga_commandというUDFが登録されていれば使えます。
ロック解放したいデータベースにuse my_dbという具合に切り替えてから実行します。

use my_db;
select mroonga_command('clearlock');
flush tables;

実行結果としては以下の通り。
行末にtrueと書かれた応答が返れば成功です。

mysql> select mroonga_command('clearlock')\G
*************************** 1. row ***************************
mroonga_command('clearlock'): true
1 row in set (0.11 sec)

もしインストールされていなければ、以下のエラーが発生します。
ERROR 1305 (42000): FUNCTION my_db.mroonga_command does not exist

groongaコマンドを利用する場合

groongaコマンドを用いた手動復旧オペレーション方法を説明します。
なお、groongaコマンドはyum install groongaでインストール出来ます。

まずはMySQLのデータディレクトリへ移動し、groonga データベース名.mrnというコマンドでファイルを開きます。
次に、clearlockと打ち込みEnterを押しましょう。
行末にtrueと書かれた応答が返れば成功です。

$ cd /var/lib/mysql
$ sudo groonga ./wikipedia.mrn
> clearlock
[[0,1368059582.565,0.113549709320068],true]
> quit
[[0,1368059584.49693,3.60012054443359e-05],true]

もし問題となったテーブルが分かっている場合には、clearlockしたらすかさず次のクエリで該当テーブルの全文検索インデックスを再構築しましょう。

  • ALTER TABLE articles DISABLE KEYS;
  • ALTER TABLE articles ENABLE KEYS;

最後に、groongaが不調となった場合にはケースバイケースですが、MySQLの再起動を行うことをオススメします。
お疲れ様でした。

あわせて読みたい

http://groonga.org/ja/docs/reference/commands/clearlock.html