MySQLのロックに関して。
データベースではデータの整合性を保つために読み書きを一時的に制限する仕組みがあります。(データベースだけではないですが・・・)
大きく分けると共有ロック(書き込みは当然だめだけど、読み取りはOK)と排他ロック(読み取りもダメ)の2種類があります。
またテーブルロックと行ロックという違いもあります。
ロック待ちtimeout(Lock wait timeout exceeded)
このロックを待っていてtimeoutしてしまうことがあります。(デッドロック)
トランザクションのスタートからコミットまでの間の処理が長く、この間に強制終了した時などはLock wait timeout exceeded・・・のようなエラーメッセージが出て、以降のDBへの書き込みができないときがあります。
あるトランザクションが終わり切らないうちに、別のトランザクションが発生するとこのようなことになるかと思います。
解除方法としてはMySQLにログインしてロックされているプロセスを消すことになります。
この場合、行ロックではなくテーブルロックになっていることが原因なことが多いです。
id指定などの行に対するロックであればロック待ちは基本発生しないからです。
ロック待ちでハマる前に知りたかったMySQL InnoDBの行ロックとテーブルロックの挙動
その他
サブクエリでのupdate
MySQLでは同じテーブルに対するサブクエリからの操作ができません。
例えば下記のようなSQLが通らず
ERROR 1093 (HY000): You can’t specify target table ‘reportitems’ for update in FROM clauseというエラーがでてしまいます。
1 2 3 |
update reportitems ri2 set ri2.is_delete = 1 where ri2.id IN ( select ri.id from reportitems ri join reports r on ri.report_id = r.id where r.customer_id= 42 ); |
この場合、サブクエリ内をテーブルとみてあげれば大丈夫です。
1 2 3 4 5 |
update reportitems ri2 set ri2.is_delete = 1 where ri2.id IN ( select id from ( select ri.id from reportitems ri join reports r on ri.report_id = r.id where r.customer_id= 42 ) as tmp ); |