PostgreSQL 和锁定
希望一些比我更聪明的 DBA 可以帮助我找到一个好的解决方案来完成我需要做的事情。
为了便于讨论,我们假设我有一个名为“work”的表,其中包含一些列,其中一列代表给定客户端对该行工作的所有权。场景是,我将连接 2 个客户端并轮询表以查找要完成的工作,当出现一行(或某些行)时,选择这些行的第一个客户端也会更新它们以暗示所有权,即更新将删除这些行,使其不会返回到任何其他客户端的选择。我的问题是,在这种情况下,我可以使用哪种锁定来防止 2 个客户端同时访问表,并且它们都通过 select 返回相同的行?
Hopefully some smarter DBAs than I can help me find a good solution for what I need to do.
For the sake of discussion, lets assume I have a table called 'work' with some number of columns, one of which is a column that represents ownership of that row of work from a given client. The scenario is that I'll have 2 clients connected and polling a table for work to be done, when a row (or some number of rows) shows up, the first client that selects the rows will also update them to imply ownership, that update will remove those rows from being returned to any other client's selects. My question is, in this scenario, what sort of locking can I use to prevent 2 clients from hitting the table at the same time and both of them being returned the same rows via the select?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
带有 RETURNING 子句的 UPDATE 语句就是执行此操作的方法。
参考文献:
类似问题
文档
The UPDATE statement with RETURNING clause is the way to do this.
REFERENCES:
Similar Question
Documentation
这里不需要锁定。
在
UPDATE
中,只需指定您只希望脚本在所有者仍为null
时获取任务的所有权(假设这就是您标记未分配任务的方式)。这应该有效:如果修改的行数等于您预期的数量(或者 RETURNING 子句返回 @Ketema 建议的结果),那么您成功地获得了所有权。
虚假编辑,因为我在提交此答案之前注意到您的评论:
正确的。您可能想阅读 MVCC。在事务外部运行这些语句将执行正确的操作。事务内的行为会有所不同。
No locking needed here.
In the
UPDATE
, simply specify that you only want the script to take ownership of the task if the owner is stillnull
(assuming that's how you flag unassigned tasks). This should work:If the number of modified rows is equal to the number you expected (or a
RETURNING
clause returns results as suggested by @Ketema), then you successfully grabbed ownership.Fake edit because I noticed your comment mere moments before submitting this answer:
Correct. You might want to read up on MVCC. Running these statements outside of a transaction will do the right thing. Behavior inside a transaction will be different.