2013年2月MySQLの行ロックのふしぎ挙動で夜も安心して眠れないコメントを残すMySQLのびみょーな行ロックに悩まされたのでメモ代わりに。全部MySQL5.5でInnoDB使っている時のお話デス。こんなテーブルが有るとしますよ。text);そしてこんなデータが入っています。|+----+-----------------+まあ、データの中身は気にしない方向で。そんなアイマス好きのAさん。行ロックを取得すべく以下のようなSQLを実行します。|+----+-----------------+そんな作業中、別の人(プロンプトBね)が何かしようとしていますよ。update;はい、なぜかBさんはここでロックかかってしまいました。なんて行は存在しないのですぐに返ってきて欲しいのですが、なぜ?ところでAさん、伊織さまの悪口修正作業が終わったみたいですね。commit;ふう、無事に悪口を消してやったぜ。なんということでしょう、Aさんがコミットした瞬間にBさんのロックが解かれたのです!えええええええええ、なんでAさんの行ロックがBさんを止めるわけ?????そしてAさん、id=5を追加しようとしました。これテーブルロックかかってね?そう、実にMySQLの行ロック周りはクセのある動きをしやがるのです。この場合、Bさんの打ったSQLがポイント。update;ポイントはカラムname。一意に定まらないカラムに対して検索かけるとテーブルロックをかけようと振舞いやがります。BさんのselectがAさんのロックとかち合ってすっ止まりやがり、そしてAさんがコミットしたら、今度はBさんのテーブルロックがかかるのでAさんのinsertがすっとまる。えええええええええ、なにこれ?????逆に一意に定まるカラム(この場合はidの方)は、存在しなくてもテーブルロックかけたりしません。さっきの例だとBさんは以下のSQLなら何事も無く動いたでしょう。update;id=100なんて存在しない主キーのためロックもかかりません。当然だよね、存在しないんだから。行ロックを取りたい時は必ず一意に決まるカラムで検索しましょう。主キーとかユニークキーとかでね。なると、例えば検索条件が主キー+制約なしのカラムだとどうなるか、試してみたくなりますね。そこでこんなテーブルを作りますた。int);このテーブルにはこんなデータが入ってます。|+----+-----------------+------+くっ...さて、さっそく主キー+制約なしカラムで行ロックを取得しましょう。|+----+-----------------+------+そしてBさんもなにかやってみます。update;→Aさんのロックに引っかかる。update;→問題なく取得成功。update;→問題なく取得成功。update;→問題なく取得成功。update;→問題なく取得成功。うーん、なんともしっくり来ませんが、これがMySQLの振る舞いでやがりますよ。ある「存在すればupdate、存在しなければselect」なんてやる時に、必ず検索条件が主キーかユニークキーになっていなければ、なんと恐ろしいことになるのやら。