gpt4 book ai didi

postgresql - PostgresQL 中超出堆栈深度限制(删除触发器后)

转载 作者:行者123 更新时间:2023-11-29 13:02:26 25 4
gpt4 key购买 nike

CREATE TABLE parent (
parent_id VARCHAR(255) PRIMARY KEY
);

CREATE TABLE child (
parent_id VARCHAR(255) REFERENCES parent ON DELETE CASCADE,
child_id VARCHAR(255) PRIMARY KEY
);

CREATE OR REPLACE FUNCTION delete_parent()
RETURNS TRIGGER AS $$
BEGIN
DELETE FROM parent WHERE parent_id = OLD.parent_id;
RETURN NULL;
END; $$ LANGUAGE 'plpgsql';

CREATE TRIGGER delete_parent AFTER DELETE
ON child
FOR EACH ROW
EXECUTE PROCEDURE delete_parent();

错误:

超出堆栈深度限制提示:'在确保平台的堆栈深度限制足够后,增加配置参数“max_stack_depth”(当前为 6144kB)。'

背景:

  • 一个parent可以有很多children
  • 该模式的设计目的是,如果删除了一个parent,它的所有子记录也将被删除。
  • 如果一个child被删除,trigger会删除parent,然后cascade会删除与那个相关的所有其他child parent

这已经工作了几个月,今天我们突然开始收到这个错误。

虽然可能存在无限递归,但我找不到,我正在考虑将堆栈深度限制加倍,看看会发生什么。

注意:实际的模式比这更复杂,并且有一些更多的相关表具有 CASCADE 删除约束。但这是唯一的触发因素。

更新:所以我将 max_stack_depth 限制加倍,现在没问题了。我认为这不是一个好的解决方案,而且我仍然不确定如何才能防止这种情况在未来发生。

最佳答案

到目前为止,你就是这样:

  1. 删除 child1。
  2. 触发删除父项。
  3. 通过 DELETE CASCADE 删除 child1 的 n 个 sibling 。
  4. 调用同一触发器 n 次。
  5. 没有 sibling 了。

没有死循环,但仍有 n 次触发器调用。这可以解释为什么超出了堆栈深度限制,但您可以通过增加限制来解决它。如果 n 更大,同样的情况可能会再次发生。

作为替代方案,将您的触发器替换为:

CREATE OR REPLACE FUNCTION delete_family()
RETURNS TRIGGER AS
$func$
BEGIN
DELETE FROM child WHERE parent_id = OLD.parent_id;
DELETE FROM parent WHERE parent_id = OLD.parent_id; -- done after 1st call
RETURN NULL;
END
$func$ LANGUAGE plpgsql; -- don't quote the language name!

CREATE TRIGGER delete_family
AFTER DELETE ON child
FOR EACH ROW EXECUTE PROCEDURE delete_family();

并用 没有 ON DELETE CASCADE 的版本替换 FK 约束。代码示例:

现在,要DELETE 整个家庭,您不能像以前那样删除父级(现在被 FK 禁止)。而是 DELETE 任何 child 。

也应该更快。

关于postgresql - PostgresQL 中超出堆栈深度限制(删除触发器后),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25465122/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com