銀河鉄道~ぽんこつエンジニアのブログ~

思いつきで書いています。

MySQL5.7でSELECTでロックが保持されてしまう

MySQLで日次バッチ実行中に、ロック待ちタイムアウトが発生しエラーとなりました。

java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction


原因はもう一つ裏で動いていたプロシージャーB。
そのプロシージャー内の処理で、以下のように記述をしていた箇所で、
なぜか行ロック(Sロック)を取得していました。

※カーソルによるループ

start transaction;

    if exists( select 1 from t_table where id = xxxx ) then
        /* 何らかの処理 */
    end if;

commit;


そのため、プロシージャーAでt_tableのid = xxxx のデータをUPDATEしようとしてロック待ちが発生し、
プロシージャーBの処理が長引いたため、タイムアウトが発生したようです。

select ~ for updateをつけているわけでもなく、単純なSELECT文なのに
Sロックを取得する理由がわからず...。
ちなみに分離レベルは、REPEAD TABLEでした。

いったん上記を下記のように修正したところ、ロックを取得することはなくなりました。

※カーソルによるループ

start transaction;

    select count(*) into HOGE from t_table where id = xxxx;

    if HOGE > 0 then
        /* 何らかの処理 */
    end if;

commit;