防止Postgresql中递归查询的无限循环

问题描述 投票:0回答:2

这里:(在CTE中找到无限递归循环)是讨论如何防止递归查询中的无限循环。在那里,递归在“查询级别”被阻止——至少在关于 Postgresql 的答案中是这样。

Postgresql (10) 有没有办法实现某种安全网来防止无限递归?使用

statement_timeout
是一种可行的方法还是有其他广泛接受的方法?

postgresql common-table-expression recursive-query
2个回答
24
投票

在我的开发环境中,我总是使用两个保险丝来进行递归查询或函数。我的客户端在启动时自动设置

set statement_timeout to '10s'

我很少需要更多,而且通常它可以让我免于死循环。

当我从头开始编写递归查询时,我总是使用一个附加列来限制所涉及的级别数,如下所示:

with recursive cte (root, parent, depth) as (
    select id, parent_id, 1
    from ...
union all
    select c.id, t.parent_id, depth+ 1
    from ...
    where depth < 10
)
select * 
from cte;

在生产中这两种方式都可能存在问题。相反,您可以根据操作系统和/或硬件的预期需求和功能调整配置参数 max_stack_depth(整数) 的值。

另请参阅此答案,了解 Postgres 14+ 中新功能的替代方法和示例。


0
投票

对于父子关系,只需将

UNION ALL
替换为
UNION
即可防止递归查询中的无限循环。我怀疑
UNION ALL
在递归查询中是否非常有用。这是 PostgreSQL 网站上描述的算法:

  1. 评估非递归项。对于

    UNION
    (但不是
    UNION ALL
    ), 丢弃重复的行。 将所有剩余行包含在结果中 递归查询,并将它们放在临时工作表中。

  2. 只要工作台不为空,就重复这些步骤:

    • (a) 评估递归项, 替换当前内容 递归自引用的工作表。 对于

      UNION
      (但不是
      UNION ALL
      ), 丢弃重复的行和重复的行 上一个结果行。将所有剩余行包含在结果中 递归查询,并将它们放在临时中间 表。

    • (b) 替换内容 工作表的内容 中间表,然后清空中间表。

这里 2.a 确保在计算递归项时丢弃重复项,因此无限循环在此时中断。

© www.soinside.com 2019 - 2024. All rights reserved.