読者です 読者をやめる 読者になる 読者になる

ありがとう。また会おう。

まぁゆるりとやっていきますよと。

レコードがなかったらINSERTして返すみたいなのをもっと確実にやる

元ネタ

レコードがなかったらINSERTして返すみたいなのを確実にやる | おそらくはそれさえも平凡な日々
http://www.songmu.jp/riji/entry/2014-03-02-find-or-create-surely.html

このソースコードの処理だと

# エラーが発生していて重複エラーだったら取り直す

# ロックかけたいときは取り直す

の処理の間に、該当レコードがDELETEされてしまうと
空行にFOR UPDATEしてしまい、ギャップロックの悪夢再び、になってしまうかと。

どうしても確実にやりたい、でも、ON DUPLICATE KEY UPDATEも
INSERT IGNOREも、(元ネタには言及ないけど)REPLACE INTOも嫌!ってことなら
「ロック専用テーブル」を作るのがいいのではないかなと。

処理をかけたいテーブルと同じPKを持つテーブルを作る。(複合キーなら同じく複合で)
このロック専用テーブルには他のカラムは要らない。

で、トランザクションの最初に、
ロック専用テーブルにこれから処理しようとしているデータのPKをINSERT。

本来やりたい処理(レコードがなかったらINSERT)を行う

ロック専用テーブルにINSERTしたデータを削除してからコミット

こうすれば、いけるんじゃないかしら。
並行スレッドは、処理をしようとしても、最初のロック専用テーブルのINSERTに失敗するから
処理できないはず。
一方、ロック専用テーブルにはPKを直接指定してINSERTしてるので
このケースの時はネクストキーロックはかからないんじゃなかったかな。。。ちょっと記憶が曖昧。
実際動作確認したわけじゃないので
嘘書いてたらごめん。

まぁ、このためだけに、一見何も入ってないテーブル
トランザクション開始時にINSERTして、コミット直前にDELETEしちゃうから)
を作らなきゃいけないってのがうざいので
許容できる状況なら ON DUPLICATE KEY UPDATEがおすすめかな。