InnoDBのネクストキーロックによるデッドロックの例

あまりMySQLのことは自信ないですが。

一見問題なさそうに見える操作でデッドロックしてしまうケースがあったので動画にしてみました。

SELECTしてみて「有ればUPDEATE、無ければINSERT」や、あるいは「有れば何もせず、無ければINSERT」を行ないたい場合に、SELECT FOR UPDATEして無ければINSERTとしてしまうと、動画の最初の例のようにデッドロックしちゃいます。存在しない行に対してSELECT FOR UPDATEするとちょっと広めに行ロックがかかってしまう感じでしょうか。

「有ればUPDATE、無ければINSERT」であれば、INSERT ... ON DUPLICATE KEY UPDATEを使うのが良さそう。「有れば何もせず、無ければINSERT」なら、いきなりINSERTしてみて一意制約違反ではじいてもらうのがいいのかな。

動画の2つめの例は、i = 100が存在するときに、WHERE i = 200 FOR UPDATEすると、100より大きい側はロックされるが100より小さい側はロックされないようだ、という実験。

動画の3つめの例は、存在する行に対してSELECT FOR UPDATEした場合の例です。

あと、存在しない行に対するDELETEやUPDATEでも、ちょっと広めの行ロックが発生するようです。

関連