MySQL でレコードを掴んでしまっているプロセスが発生するケースがあります。
例えば、特定のレコードをロックしたままトランザクションタイムアウトになったものの、ロールバックされないとか・・・。
Spring の @Transactional アノテーションの挙動に悩まされる場面が時々あるのですよね。
@Transactional(timeout = 10, rollbackFor = [Exception::class])
まあ、問題のプロセスを kill すれば解決なのですが、AWS の RDS では素直にいかないようで・・・。
今回は RDS で特定のプロセスを kill する方法を紹介します。
ロックプロセスの確認
MySQL で DB(ストレージエンジンは InnoDB とします)の状態を確認するには、以下のコマンドを実行。
SHOW ENGINE INNODB STATUS\G;
これでトランザクションの状態をチェックすることができます。
チェックすべき箇所は「TRANSACTIONS」の段落の最後の方。
以下のサンプルだと「—TRANSACTION」の項目ですね。
1 2 3 4 5 6 7 8 9 10 11 | ------------ TRANSACTIONS ------------ (省略) ---TRANSACTION xxxxxx, ACTIVE 580 sec 12 lock struct(s), heap size 1136, 7 row lock(s) MySQL thread id 9999, OS thread handle xxxxxx, query id 9999 ... (省略) |
ここに、「MySQL thread id 9999」と書かれていますが、この 9999 がプロセス ID になります。
このプロセスを kill してあげれば、ロック自体の問題は解決なのですが・・・。
MySQLのkillコマンド
MySQL でプロセスを kill するには kill コマンドを使います。
おやっ、「You are not owner」という明らかに権限周りのエラーが出力されます。
1 2 3 | mysql> kill 9999; ERROR 1095 (HY000): You are not owner of thread 9999 |
どうやら RDS では、マスターユーザーに対して kill の実行権限はないようですね。
RDSのkillコマンド
RDS には以下のプロシージャが用意されています。
mysql.rds_kill(processID)
これを CALL コマンドで実行してあげればいいですね。
無事に実行でき、プロセスも消えました。
1 2 3 | mysql> CALL mysql.rds_kill(9999); Query OK, 0 rows affected (0.00 sec) |
ちなみに実行中のクエリを終了させるには、以下のプロシージャを使います。
mysql.rds_kill_query(queryID)
ID が 9999 ならこんな感じ。
1 2 3 | mysql> CALL mysql.rds_kill_query(9999); Query OK, 0 rows affected (0.00 sec) |
プロセスかクエリかは、information_schema.PROCESSLIST のテーブルの COMMAND カラムで判断ですね。
スレッドのコマンド一覧は下記のページで確認できます。
まとめ
RDS におけるプロセスやクエリの終了方法について紹介してきました。
プロセスを強制的に終了させるケースは滅多にないと思いますが、データベース周りの運用コマンドは最低限覚えておきたいですね。
コマンドの詳細は忘れたとしても、知識として持っているだけで十分。
いざ問題が発生した際に、焦らずに落ち着いて調査に入りたいですね。