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

在我看来,可能存在这样的情况:线程1和线程2都在彼此的微秒内执行选择,并且都看到该行处于状态1,然后两者都执行相同的操作并且在锁具有之后发生2次更新被释放了。

问题是:有没有办法阻止第二个线程能够在Postgres中修改这个数据 - AKA在第一个线程的锁被释放后才被强制执行另一个SELECT ,因此它知道要保释以便防止欺骗?

我查看了行锁定,但是它说你无法阻止选择语句,听起来这对我的条件不起作用。 我唯一的选择是使用咨询锁吗?

#1楼 票数:7 已采纳

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

我查看了行锁定,但是它说你无法阻止选择语句,听起来这对我的条件不起作用。 我唯一的选择是使用咨询锁吗?

关于此事的官方文件:

行级锁不会影响数据查询; 他们只阻止作家和储物柜到同一行。

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

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

在Postgres 9.5+中考虑为此FOR UPDATE SKIP LOCKED 就像@Craig评论的那样 ,这可以在很大程度上取代咨询锁。

相关问题磕磕绊绊的同一性能猪:

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

一次锁定多行

#2楼 票数:2

你想要的是相当常见的SQL SELECT ... FOR UPDATE Postgres特定的文档在这里

使用SELECT FOR UPDATE将锁定事务跨度的选定记录,允许您在另一个线程可以选择之前更新它们。

  ask by BryanP translate from so

未解决问题?本站智能推荐:

2回复

如何锁定某些列在postgresql中为用户编辑

即使用户有权访问postgresql中表的编辑权限,如何锁定某些列也不会被编辑。
1回复

将列从时间戳更改为时间戳会锁定表吗?

我想将列从timestamp (无时区)迁移到timestamptz类型。 我正在使用Postgres 9.3.9。 我需要知道此操作是否会导致表重写(锁定表),因为我的表很大并且数据库处于活动状态。 我在9.2发行说明中发现了这一点: 增加varchar或varbit列的长度
1回复

多个事务期间的数据库行锁定

嗨,新年快乐:) 我正在使用Postgresql,我需要一种方法来使工作进程锁定特定行,而该进程在该行上运行。 它本质上是一个动作表,应该只执行一次。 每个进程都应抓住不同的行进行操作。 在此“操作”过程中,工作进程将计算一些值并多次插入事务中(在计算和插入数据库之间会有所不同)。
1回复

插入和选择时postgresql如何锁定表?

我正在将数据从一个表迁移到另一个表,在这种环境中,任何长锁或停机时间都是不可接受的,总共大约 80000 行。 本质上,查询归结为这个简单的案例: 正在读取所有 3 个表,并且可以随时插入。 我只想运行上面的查询,但我不确定锁定是如何工作的,以及在操作过程中表是否完全无法访问。 我的理解告诉我,只有
1回复

INSERT...SELECT是原子事务吗?

我使用这样的查询: 我的问题是关于FOR UPDATE t2 SKIP LOCKED 。 我应该在这里使用它吗? 或者 Postgres 会使用INSERT SELECT ON CONFLICT自动锁定这些行直到事务结束? 我的目标是防止其他应用程序(同时)使用内部SELECT捕获已被此应用程序捕获
2回复

如何为PostgreSQL编写自己的全局锁定/解锁函数

我有pergre的postgresql函数getTravelTime(integer,timestamp),它试图为指定的ID和时间戳选择数据。 如果没有数据或数据很旧,它将从外部服务器下载数据(下载时间约为300毫秒)。 多进程使用此数据库和此功能。 当两个进程找不到数据并下载并尝试在
2回复

应该阻止查询的postgres中的锁定和事务

让我们假设在 SQL 窗口 1 中我这样做: 然后从另一个窗口(窗口 2)我做: 我得到: 这很好,因为默认隔离级别是 READ COMMITTED 并且因为查询 1 从未提交,所以它执行的更改在我从窗口 1 显式提交之前是不可读的。 事实上,如果我在窗口 1 中执行以下操作: 如果我重新运行查询
1回复

postgres:插入前删除需要锁定?

我想替换客户的记录列表。 postgres 似乎没有处理我的案例的merge语句,我决定按如下方式进行: 我像这样删除客户的所有记录DELETE FROM SOME_TABLE WHERE SOME_TABLE.CLIENT_ID=? 然后插入一些新记录: INSERT INTO SOME_TAB