Hal ini dapat terjadi pada tingkat konkurensi yang tinggi.
Menurut dokumen Rails, kueri berikut akan dijalankan:
SELECT * FROM games WHERE status = 'waiting' AND ... LIMIT 1;
INSERT INTO games (status, ...) VALUES ('waiting', ...);
Yang kedua hanya berjalan, ketika yang pertama belum mengembalikan satu baris pun.
Mungkin saja, jika dua (atau lebih) koneksi memulai kueri pertama dalam beberapa mikrodetik, beberapa proses akan membuat banyak entri. Untuk mencegahnya, Anda dapat menggunakan ACCESS EXCLUSIVE
lock pada tabel tersebut , atau gunakan kunci penasehat khusus.
Anda juga dapat menggunakan beberapa indeks unik, untuk mencegah banyak entri dimasukkan ke dalam database Anda, namun jika digunakan sendiri, hal itu akan menyebabkan pengecualian SQL dalam situasi ini.
EDIT:
ACCESS EXCLUSIVE
kunci dapat diperoleh melalui LOCK
perintah.
Kunci penasehat dapat diperoleh melalui penggunaan pg_advisory_lock(id)
fungsi.
Keduanya mengharuskan Anda menjalankan perintah SQL sewenang-wenang.
Cara lain adalah dengan menggunakan kueri khusus dengan:
- masukkan hanya jika tidak ada (& kembalikan dengan semua bidang)
- pilih hanya jika tidak dimasukkan
Sesuatu seperti:
INSERT INTO games (status, category_id, private)
SELECT 'waiting', 2, 0
WHERE NOT EXISTS (
SELECT 1
FROM games
WHERE status = 'waiting'
AND category_id = 2
AND private = 0
)
RETURNING *;
-- only select, when this not inserted anything
SELECT *
FROM games
WHERE status = 'waiting'
AND category_id = 2
AND private = 0
person
pozs
schedule
22.05.2014
is_new
digunakan dalam kode berikut, hanya untuk mengetahui bahwa catatan baru saja dibuat. - person Alexander Zinchuk   schedule 22.05.2014