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();
错误:
stack depth limit exceeded
提示:'确保平台的堆栈深度限制足够后,增加配置参数“max_stack_depth”(目前为6144kB)。
背景:
parent
可以有多个children
parent
,则还会删除其所有子记录。 child
,则触发器会删除parent
,然后级联删除与该children
相关的所有其他parent
这已经工作了几个月,今天我们突然开始出现这个错误。
我无法找到可能存在无限递归的情况,我正在考虑将堆栈深度限制加倍,看看会发生什么。
注意:实际模式比这更复杂,并且有一些更多相关的表具有CASCADE删除约束。但这是唯一的触发因素。
UPDATE :所以我将max_stack_depth限制加倍,现在没问题了。我不认为这是一个很好的解决方案,我仍然不确定如何防止将来发生这种情况。
答案 0 :(得分:2)
到目前为止,你发生了什么:
n
删除child1的 DELETE CASCADE
兄弟姐妹。n
次。没有无限循环,但仍然 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();
并使用版本 替换FK约束而不使用 ON DELETE CASCADE
。代码示例:
现在,对于DELETE
整个家庭,你不能像以前一样删除父母(现在被FK禁止)。而是DELETE
任何孩子。
也应该更快。