0

情况:

PostgresSQL 数据库。使用 SQL Alchemy ORM 的应用程序(不是很重要)。具有数百万行的表。

数百个进程使用该表访问数据库。每个人都想选择一行并根据其内容执行相对昂贵的操作,然后填充其他表并更新该行。

我使用的天真的方法是这样的:

SELECT * FROM table WHERE status = 'free';

然后在那之后:

UPDATE table SET status 'in_process';

现在的问题是这些操作不是原子的,这意味着在 和 之间的时间SELECTUPDATE,最多 5 个其他进程可以选择该行并开始处理它(我提醒你,这非常昂贵)。

现在我知道有SELECT FOR UPDATE哪些锁定行。但是它会锁定它们FOR UPDATE(duh),它不会禁止选择行。

所以我想这一定是一个非常普遍的问题,但谷歌搜索并没有多大帮助。

4

2 回答 2

1

SELECT ... FOR UPDATE是一种很好的技术,因为它们会相互阻止,因此在您的交易完成之前,没有其他具有相同意图的人可以获取您的行。

SKIP LOCKED如果您想忽略被其他人锁定的行,您可以添加该子句。

可能对您有吸引力的替代方案是

UPDATE atable
SET status = 'in_progress'
WHERE status = 'free'
RETURNING *;
于 2019-03-01T07:08:25.000 回答
0

似乎这是解决此问题的一种方法:

使用 python 和 sqlalchemy(但这不是必要的,因为我还是使用原始 SQL)

from sqlalchemy import text
sql = text("UPDATE table 
            SET status = 'in_process' 
            WHERE column.id = (SELECT column.id 
                               FROM table 
                               WHERE status='free' 
                               AND pg_try_advisory_xact_lock(column.id) 
                               LIMIT 1 FOR UPDATE) 
            RETURNING *"
row = next(iter(engine.execution_options(autocommit=True).execute(sql)))
# Now row is a tuple of values
于 2019-03-01T08:25:38.923 回答