BEGIN;
LOCK TABLE slots IN ACCESS EXCLUSIVE MODE;
UPDATE slots SET job_name = '111' WHERE id IN (SELECT id FROM slots WHERE job_name IS NULL LIMIT 1) RETURNING *;
COMMIT;
これはReadCommittedで機能するようです。これはSQL(コードと同じ)のみであり、1回の呼び出しで(より高速に)実行できます。
@Seth Robertson:LOCKTABLEとwhileループがないと安全ではありません。
トランザクションAとトランザクションBが同時に存在する場合:Aは最初の行を選択し、Bは最初の行を選択します。 Aは行をロックして更新し、BはAがコミットするまで待機する必要があります。次に、Bは条件job_nameISNULLを再チェックします。これはfalseであり、Bは更新されません。Bは次の行を選択せず、再チェックして空の結果を返すだけです。
@joegester:すべてのテーブルがロックされているため、SELECTFORUPDATEは問題ではありません。
たぶん、仕事をする別の方法があります-代わりにNULLを設定する代わりに(他のテーブルに?)行を削除して挿入する場合。しかし、その方法はわかりません。