このクエリがMySQLによって実際にどのように実行されるかを確認すると役立つ場合があります:
select * from tbl_codes where available = 1 order by rand() limit 1 for update
これにより、WHERE
に一致するすべての行が読み取られて並べ替えられます 条件、rand()
を使用して乱数を生成します 各行の仮想列に変換し、その仮想列に基づいて(一時テーブル内の)すべての行を並べ替えてから、並べ替えられたセットからLIMIT
まで行をクライアントに返します。 到達します(この場合は1つだけ)。 FOR UPDATE
実行中にステートメント全体によって実行されるロックに影響します。そのため、InnoDB内で行が読み取られるときに句が適用されます。 、ない クライアントに返されるので。
上記の明らかなパフォーマンスへの影響は別として(それはひどいです)、それから合理的なロック動作を得ることが決してありません。
簡単な答え:
-
RAND()
を使用して、目的の行を選択します または、PRIMARY KEY
を見つけるためのその他の戦略 その行の値。例:SELECT id FROM tbl_codes WHERE available = 1 ORDER BY rand() LIMIT 1
-
PRIMARY KEY
を使用して目的の行をロックします それだけ。例:SELECT * FROM tbl_codes WHERE id = N
うまくいけば、それがお役に立てば幸いです。