【问题标题】:Row locking in recursive query递归查询中的行锁定
【发布时间】:2019-02-06 19:54:45
【问题描述】:

documentation 说:

锁定子句不能用于返回的行不能与单个表行明确标识的上下文中;例如,它们不能与聚合一起使用。

如何在使用UNION (ALL) 实现的递归查询设置中解决此问题?

有没有比再次将递归查询的结果与表连接起来更好的解决方案,这次是FOR UPDATE?我必须为这个查询锁定整个表,以确保连接不会同时发生任何变化,对吧?

【问题讨论】:

  • 是什么让您认为聚合与递归查询有任何关系?

标签: sql postgresql


【解决方案1】:

是什么让您认为聚合与递归查询有关?似乎对我有用,

CREATE TABLE foo(pk,fk,description)
AS VALUES
    ( 1 , null , 'domains' ),
    ( 2 , 1 , 'people' ),
    ( 3 , 1 , 'cars' ),
    ( 4 , 2 , 'tom' ),
    ( 5 , 2 , 'smith' ),
    ( 6 , 3 , 'vmw' ),
    ( 7 , 2 , 'betty' ),
    ( 8 , 3 , 'ford' );

WITH RECURSIVE t(pk, fk, description, level) AS (
    SELECT pk, fk, ARRAY[description], 0
    FROM foo
    WHERE fk IS NULL
    UNION ALL
        SELECT foo.pk, foo.fk, t.description || foo.description, t.level+1
        FROM t
        JOIN foo ON (foo.fk = t.pk)
)
SELECT *
FROM t
FOR UPDATE;

Example taken from example on this question on dba.se

【讨论】:

  • WITH RECURSIVE 包含 UNION ALL 不是吗? ;) 在递归查询期间更改 foo 时,您的示例中不会出现竞争条件吗?这些行仅在SELECT FROM t 运行后才被锁定,对吗?我需要在递归查询中遇到行时立即锁定它们。
  • 在进行递归之前,您不知道要访问哪些行。当您进行递归时,行被添加到输出结果集中并被锁定。就像 READ COMMITTEDSELECT .. FOR UPDATE 的任何东西一样
  • 你可能是对的,但你能引用任何资料来证明你的说法吗?我相信这些行在结果集完成后被锁定,而不是在添加它们后立即锁定。在this 之后,我知道“外部”选择与递归 CTE 有点同时运行,但我想确保在访问一行时立即发生锁定。
  • "但我想确保在访问一行时立即发生锁定。"如果您问的是数据库内部问题,那么我猜您将不得不重写一个全新 问题,询问实际锁定何时发生。因此,我不会深入研究源代码来弄清楚这一点。我的假设是返回的行被立即锁定,但我可以看到这是一个复杂的问题,涵盖了仅索引扫描等情况。
  • 当然,我不希望您仅仅为了回答我的问题而挖掘源代码。感谢您迄今为止的帮助!
猜你喜欢
  • 2013-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-16
  • 2017-04-12
  • 2020-07-29
相关资源
最近更新 更多