在我的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