在PostgreSQL中,对同一表中不同行的多个UPDATE是否存在锁定冲突?

Zso*_*nos 1 postgresql locking

我有点想知道我正在做一张大桌子的更新,我是否需要担心锁。

我有一张桌子,看起来像这样:

CREATE TABLE "ItemsToProcess"( 
"id" text, 
"WorkerInstanceId" text, 
"ProcessingStartTime" timestamp with time zone, 
"UpdatedTime" timestamp with time zone, 
CONSTRAINT "ITP_PK" PRIMARY KEY ("id")
)WITH (
  OIDS=FALSE
);
Run Code Online (Sandbox Code Playgroud)

最初,此表中有〜200万行,并且默认情况下以及运行开始时,仅填充的ID,WorkerInstanceId和两个时间戳为null。

发生的情况是,某些工作人员应用程序(至少两个,但在生产中大约为10-13)会从该表中标记一批ID-s(我计划将batchSize设置为200)进行处理。处理过程中发生的事情现在并不重要。批处理的标记如下所示:

UPDATE "ItemsToProcess" 
   SET "WorkerInstanceId" = ?, "ProcessingStartTime" = current_timestamp()
 WHERE "WorkerInstanceId" is NULL
 LIMIT 200;
Run Code Online (Sandbox Code Playgroud)

我的问题是,在进行更新之前,我是否需要担心锁定要更新的行?

Postgres文档说:

排他性

与SHARE,SHARE ROW EXCLUSIVE,EXCLUSIVE和ACCESS EXCLUSIVE锁定模式冲突。

命令UPDATE,DELETE和INSERT在目标表上获得此锁定模式(除了对任何其他引用表的ACCESS SHARE锁定之外)。通常,任何修改表中数据的命令都将获取此锁定模式。

因此,我认为每当一个工作人员进行此更新时,整个表将被锁定,将更新200行,最后释放该锁。在锁到位之前,其他工人正在等待锁释放。我是对的还是我想念什么

谢谢您的帮助!

Cra*_*ger 5

UPDATE锁定行,因此您不需要先锁定它。如果尝试同时UPDATE重叠行集,则第二个UPDATE将等待第一个的事务提交或回滚。

您的方法最大的问题-除了UPDATE没有LIMIT子句的事实之外-多个工作人员都将尝试抓住同一行。这是发生了什么:

worker1:过滤表以查找200行并将其锁定worker1:开始更新行worker2:过滤表以查找200行row2:尝试开始更新行,但是选择了与worker1相同的行,因此它阻塞了worker1的锁worker1:完成更新worker2行:释放锁定后,重新检查WHERE条件,发现没有行匹配,因为worker1已更新它们。更新零行。...然后重复!

您需要:

  • 有一个中央队列以适当的并发安全方式分发行;要么
  • 分配工作人员ID的非重叠范围

至于LIMIT-您可以使用WHERE id IN (SELECT t.id FROM thetable t LIMIT 200 ORDER BY id)-但两个工人选择相同的行集进行更新会遇到相同的问题。

  • @MarkStosberg是的。我不想详细介绍排队。还有来自skytools的PgQ:http://wiki.postgresql.org/wiki/PGQ_Tutorial (2认同)