在我的Rails應用4,我有這樣的查詢到一個Postgres 9.4數據庫:諮詢鎖或NOWAIT以避免等待鎖定的行?
@chosen_opportunity = Opportunity.find_by_sql(
" UPDATE \"opportunities\" s
SET opportunity_available = false
FROM (
SELECT \"opportunities\".*
FROM \"opportunities\"
WHERE (deal_id = #{@deal.id}
AND opportunity_available = true
AND pg_try_advisory_xact_lock(id))
LIMIT 1
FOR UPDATE
) sub
WHERE s.id = sub.id
RETURNING sub.prize_id, sub.id"
)
很受this related answer on dba.SE啓發。
我只是希望我的查詢來查找和更新的第一個(隨機,與LIMIT
)排在那裏available = true
和其更新爲available = false
,我需要鎖定該行,而這樣做,但沒有使等待發行的新要求因爲有很多併發呼叫將使用此查詢。我也看到NOWAIT
選項FOR UPDATE
。我不知道我的理解使用pg_try_advisory_xact_lock()
和NOWAIT
選項之間的差別,他們似乎對我達到同樣的目標:
-
要防止等待其他操作要提交的事務,請使用
NOWAIT
選項。 pg_try_advisory_xact_lock
's goal
不是等待一個事務解除鎖定,仍然能夠做其他事務,並只經營則下一個更新選擇「尚未鎖定」行。
哪一個更適合我的需要?
非常感謝您的詳細解答。我會盡力實施下一個星期一。是的,你是正確的更新跳過鎖定是最合適的。我可能會等待它的發佈,並在此期間使用pg顧問鎖定。因爲我的排在這個階段已經隨機分佈了,所以如果我沒有得到任意選擇,這並不重要。 – Mathieu
@Mathieu:「任意」也很重要,因爲它意味着Postgres通常會爲相同的查詢*任意*選擇*相同的*行,這使得鎖爭論比真正的隨機選擇更大。 –
你是什麼意思'它會一直選擇同一行'?如果你願意,我的應用程序是一種彩票。當玩家檢查'機票=機會'時,我會將其更新爲available = false當玩家的下一張照片出現時,它會使用我們關注的查詢並選擇任何行,其中opportunity_available =真正。所以如果查詢總是選擇同一行,因爲一旦玩家打開它就會被更新爲不可用,我不認爲這個任意的方面會影響我。你做? postgresql菜鳥 – Mathieu