【问题标题】:PostgreSQL and lockingPostgreSQL 和锁定
【发布时间】:2011-08-03 21:47:18
【问题描述】:

希望一些比我更聪明的 DBA 可以帮助我找到一个很好的解决方案来解决我需要做的事情。

为了便于讨论,假设我有一个名为“work”的表,其中包含一些列,其中一个列表示来自给定客户的该行工作的所有权。场景是我将连接 2 个客户端并轮询表以完成工作,当出现一行(或一些行)时,选择行的第一个客户端也将更新它们以暗示所有权,即update 将删除这些行,使其不再返回给任何其他客户端的选择。我的问题是,在这种情况下,我可以使用哪种锁定来防止 2 个客户端同时访问表并通过选择返回相同的行?

【问题讨论】:

  • 诸如更新工作集所有者 = 客户 ID 的所有者为空返回列之类的查询会以原子方式运行吗?例如:2 个客户端同时发出该查询,他们没有机会操作相同的行?

标签: sql postgresql locking


【解决方案1】:

我的问题是,在这种情况下,我可以使用哪种锁定来防止 2 个客户端同时访问表并通过选择返回相同的行?

这里不需要锁定。

UPDATE 中,只需指定您只希望脚本在所有者仍然是null 的情况下获得任务的所有权(假设这是您标记未分配任务的方式)。这应该有效:

UPDATE foo SET owner = ? WHERE id = ? AND owner = ? WHERE owner IS NULL

如果修改的行数等于您预期的数量(或RETURNING 子句按照@Ketema 的建议返回结果),那么您成功获取了所有权。


虚假编辑,因为我在提交此答案前不久就注意到了您的评论:

例如:2 个客户端同时发出该查询,他们没有机会操作相同的行?

正确。您可能想阅读MVCC。在事务外部运行这些语句将做正确的事情。交易内部的行为会有所不同。

【讨论】:

  • Behavior inside a transaction will be different.能否详细说明?
  • 你会想要阅读transaction isolation。根据隔离级别,您可能会看到不完全正确的事情,即使这样,您也可能会遇到死锁或冲突,并且必须单独处理。 More on wikipedia.
【解决方案2】:

带有 RETURNING 子句的 UPDATE 语句就是这样做的方法。

UPDATE table
SET ownership = owner
RETURNING ( column list );

参考文献:

Similar Question

Documentation

【讨论】:

  • 在您提供的第一个链接中,我想我有点自暴自弃。那家伙正在使用事务块并在内部执行更新然后提交它,如果我这样做,在事务执行时,我的理解是在提交发生之前可能会获取行的版本?如果是这样,在事务之外执行应该可以正常工作吗?
  • 没有。 UPDATE 语句在满足其条件的行上获取排他锁。先到先得。如果其他事务在第一个事务完成之前也符合标准,则它们将阻塞。如果此时行不再符合条件,则后续事务将出现错误,您的应用程序必须处理该错误并重试。但是,您的标准是多行满足它,但是您限制了返回 ala LIMIT,那么后续事务只会获取未采用的下一行。这是 MVCC 世界中的序列化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多