我有一个表,可以有两个线程从中读取数据。如果数据处于某种状态(假设状态 1),那么该过程将执行某些操作(与此问题无关),然后将状态更新为 2。
在我看来,可能存在这样一种情况:线程 1 和线程 2 都在彼此相隔几微秒内执行选择,并且都看到该行处于状态 1,然后都执行相同的操作,并且在锁定后发生 2 次更新已被释放。
问题是:有没有办法防止第二个线程能够在 Postgres 中修改此数据 - 也就是在第一个线程的锁被释放以进行更新后,它被迫执行另一个
SELECT
,因此它知道要放弃为了防止受骗?
我研究了行锁定,但它说你无法阻止 select 语句,这听起来似乎不适用于我的情况。使用咨询锁是我唯一的选择吗?
您的问题,引用来源不明:
我研究了行锁定,但它说你无法阻止选择 听起来这对我这里的情况不起作用的陈述。是 我使用咨询锁的唯一选择?
行级锁不影响数据查询;他们只阻止作家和储物柜到同一行。
SELECT ... FOR UPDATE
取出相同的行级锁 - 这会导致它们等待任何先前持有同一行锁的事务来提交或回滚。正是您想要的。
但是,许多用例可以通过 咨询锁更好地解决 - 在 9.5 之前的版本中。为了安全起见,您仍然可以使用
FOR UPDATE
锁定正在处理的行。但是,如果下一个事务只想处理“下一个空闲行”,那么不等待同一行通常会更高效,因为锁释放后几乎肯定不可用,而是跳到“下一个空闲行” “立即。
在 Postgres 9.5+ 中请考虑使用 FOR UPDATE SKIP LOCKED
@Craig评论的那样,这可以在很大程度上取代咨询锁。 参见:
函数需要永远运行大量记录
FOR UPDATE SKIP LOCKED
Postgres 更新...限制 1
如何在并发访问时标记表中的某些行
SELECT ... FOR UPDATE