在我的Rails 4应用中,我对Postgres 9.4 数据库进行了此查询:
@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
的{{1}}选项。我不确定我是否理解使用FOR UPDATE
和pg_try_advisory_xact_lock()
选项之间的区别,我认为他们可以实现相同的目标:
要防止操作等待其他事务提交,请使用
NOWAIT
选项。
pg_try_advisory_xact_lock
's goal
不要等待上一个事务释放锁定,仍然可以执行另一个事务,只能操作下一个选择来更新“尚未锁定”的行。
哪一个更适合我的需要?
答案 0 :(得分:6)
只是一个好主意,如果你坚持要锁定一个特定的行, 不是 < / strong>你需要什么。您只需要任何符合条件的可用(未锁定)行。重要的区别是这个(quoting the manual for Postgres 9.4):FOR UPDATE NOWAIT
对于
NOWAIT
,如果无法立即锁定选定的行,则语句会报告错误,而不是等待。
相同的查询很可能会尝试锁定相同的任意选择。 FOR UPDATE NOWAIT
只会豁免异常(除非你捕获错误,它将回滚整个事务),你必须重试。
我在dba.SE上引用的答案中的解决方案使用了简单的 FOR UPDATE
与pg_try_advisory_lock()
的组合:
pg_try_advisory_lock
与pg_advisory_lock
类似,但除了FOR UPDATE SKIP LOCKED
函数不会等待锁变为可用。它会 要么立即获得锁定并返回true,要么返回false 锁不能立即获得。
所以最佳选项是......第三种选择:Postgres 9.5中的新 NOWAIT
,它实现相同的行为而无需额外的函数调用。
The manual for Postgres 9.5比较了两个选项,更多地解释了这些差异:
防止操作等待其他事务 提交,使用
SKIP LOCKED
或NOWAIT
选项。使用SKIP LOCKED
, 语句报告错误,而不是等待,如果选定的行 无法立即锁定。使用pg_try_advisory_xact_lock(id)
,任何选定的行 不能立即锁定被跳过。
在Postgres 9.4或更早版本中次佳选项是将FOR UPDATE
与FOR UPDATE SKIP LOCKED
结合使用,如参考答案所示:
(还有@IBAction func LoginPressed(sender: UIButton) {
/*previously assigned by the app owner for the customer it is saved in the app code so it is in the phone memory(?)*/
if RutField.text == "243338743" && CodigoField.text == "1104"{
/*i'm not sure what this but is kind of a dialogue of what came first and later, You must previously assign the ViewController Identity on the "StoryBoard ID" it will help any doubt or image help contact me*/
dispatch_async(dispatch_get_main_queue()){
var Storyboard = UIStoryboard(name: "Main", bundle: nil)
var PerfilUsuario : UIViewController = Storyboard.instantiateViewControllerWithIdentifier("PerfilUsuario") as! UIViewController
self.presentViewController(PerfilUsuario, animated: true, completion: nil)
}
}
else {
TrekLogo.hidden = true
}
}
的实现。)
严格地说,你是随意的,而不是真正的随机选择。这可能是一个重要的区别 您的查询的审核版本位于my answer to your other question。