Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PostgresQL中超出堆栈深度限制(删除触发器后)_Postgresql - Fatal编程技术网

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

PostgresQL中超出堆栈深度限制(删除触发器后),postgresql,Postgresql,错误: 超出堆栈深度限制 提示:“在确保平台的堆栈深度限制足够后,增加配置参数“max_stack_depth”(当前为6144kB)。” 背景: 一个父项可以有许多子项 该模式的设计目的是,如果删除父项,则其所有子项记录也将被删除 如果删除了子项,触发器将删除父项,然后级联删除与该父项相关的所有其他子项 这已经运行了几个月,今天我们突然发现了这个错误 我找不到无限递归,我正在考虑将堆栈深度限制加倍,看看会发生什么 注意:实际的模式比这更复杂,并且还有一些具有级联删除约束的相关表。但这是唯一

错误:

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

背景:

  • 一个
    父项
    可以有许多
    子项
  • 该模式的设计目的是,如果删除父项,则其所有子项记录也将被删除
  • 如果删除了
    子项
    ,触发器将删除
    父项
    ,然后级联删除与该
    父项
    相关的所有其他
    子项
这已经运行了几个月,今天我们突然发现了这个错误

我找不到无限递归,我正在考虑将堆栈深度限制加倍,看看会发生什么

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


更新:因此我将最大堆栈深度限制提高了一倍,现在一切正常。我认为这不是一个好的解决方案,我仍然不确定如何防止将来发生这种情况。

到目前为止,你知道发生了什么:

  • 删除child1
  • 触发父项的删除
  • 通过
    DELETE CASCADE
    删除孩子1的兄弟姐妹
  • 调用相同的触发器
    n次
  • 不再有兄弟姐妹了
  • 没有无止境的循环,但仍
    n
    触发器调用。这可以解释为什么超过了堆栈深度限制,但是可以通过增加限制来修复它。如果
    n
    越大,同样的情况也可能再次发生

    或者,将触发器替换为:

    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();
    
    并将FK约束替换为一个版本,该版本在删除级联时不包含
    。代码示例:

    现在,要删除整个家庭,您不能像以前那样删除父级(现在FK禁止)。而是删除所有子项


    也应该更快。

    如果父项被删除,则通过子项->父项FK的级联删除将导致所有子项被删除。你的扳机的作用正好相反。因此,一旦孩子被删除,他的父母和兄弟姐妹就会被删除。这是你的意图吗?没错。如果子项被删除,则删除父项及其所有silbingsBTW:为什么使用varchar(255)字段作为PK和FK?它实际上不是varchar(255)。服务器现在着火了,所以我只是快速编写了一个配置示例,而不是复制真正的模式。这是一个UUID。嗨@erwin谢谢你的解决方案。似乎唯一改变的是添加了
    DELETE FROM child,其中parent\u id=OLD.parent\u id为什么这样会减少调用次数?另外,当父级被删除时,它会级联到子级,子级删除会触发再次尝试删除父级(此时不再存在)@samol:Sorry,我忘了添加基本细节:从FK约束中删除
    ON DELETE CASCADE
    。但我需要ON DELETE CASCADE触发器,因为有时我会删除父级,我需要删除该父级cascade@samol:您可以删除任何子对象以获得相同的效果。此外,我不完全确定您的问题是否由您提到的其他触发器/约束引起。
    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();