postgresql - 锁定 SELECT,这样另一个进程就不会获取旧数据

标签 postgresql concurrency locking postgresql-9.3

我有一个表,可以有两个线程从中读取数据。如果数据处于某种状态(假设状态 1),那么该过程将执行某些操作(与此问题无关),然后将状态更新为 2。

在我看来,可能有这样一种情况,线程 1 和线程 2 都在彼此相差几微秒内执行选择,并且都看到该行处于状态 1,然后两者都做同样的事情并发生 2 次更新释放锁后。

问题是:有没有一种方法可以防止第二个线程能够在 Postgres 中修改此数据 - 也就是在第一个线程的锁被释放后被迫执行另一个 SELECT它的更新使其知道保释以防止受骗?

我调查了行锁定,但它说你不能阻止 select 语句,这听起来对我这里的情况不起作用。使用咨询锁是我唯一的选择吗?

最佳答案

您的问题,引用了未知来源:

I looked into row locking, but it says you cannot prevent select statements which sounds like it won't work for my condition here. Is my only option to use advisory locks?

The official documentation on the matter:

Row-level locks do not affect data querying; they block only writers and lockers to the same row.

并发尝试不仅会选择,还会尝试取出与 SELECT ... FOR UPDATE 相同的行级锁- 这导致他们等待任何先前的事务在同一行上持有锁以提交或回滚。正是您想要的。

但是,许多用例可以用advisory locks 更好地解决- 在 9.5 之前的版本中。为了安全起见,您仍然可以使用 FOR UPDATE 锁定正在处理的行。但是,如果下一个事务只是想处理“下一个空闲行”,那么不等待同一行通常很多更有效率,这几乎肯定在锁定后不可用被释放,但立即跳到“下一个自由”。

在 Postgres 9.5+ 中考虑 FOR UPDATE SKIP LOCKED为了这。喜欢@Craig commented ,这可以在很大程度上取代建议锁。

因同一个性能问题而绊倒的相关问题:

Postgres 9.5+ 中咨询锁或FOR UPDATE SKIP LOCKED 的说明和代码示例:

一次锁定多行:

关于postgresql - 锁定 SELECT,这样另一个进程就不会获取旧数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29357105/

相关文章:

java - ConcurrentHashMap 上的迭代器

c++ - Boost 条件变量等效于 CRITICAL_SECTION

Django 设置使用两个引擎配置数据库

sql - 有没有办法在添加新值时动态更新/增加列值?

postgresql - SQLAlchemy、Psycopg2 和 Postgresql COPY

c - `mmap()` 手动并发预故障/分页

macos - Postgres : After importing production database (with replication) to my local machine, 我注意到正在从 macbook 发送和接收网络数据包

java - 多个用户的 csv 并发处理

locking - 访问 2007,使用 "edit"按钮或切换锁定表单加载时的所有字段

mysql - 如何锁定 MySQL 中的一行?