stack depth limit exceeded报错处理
文章目录
- 环境
- 症状
- 问题原因
- 解决方案
- 报错编码
环境
系统平台:Linux x86-64 Red Hat Enterprise Linux 7,Linux x86-64 Red Hat Enterprise Linux 8
版本:4.5.10,9.0.4
症状
在 HGDB数据库执行递归函数、复杂嵌套调用或触发器链时,出现以下错误信息:
ERROR: 54001: stack depth limit exceeded HINT: Increase the configuration parameter "max_stack_depth" (currently 2048kB), after ensuring the platform's stack depth limit is adequate. CONTEXT: SQL expression "recurse(n + 1)" PL/pgSQL function recurse(integer) line 1 at RETURN LOCATION: check_stack_depth, postgres.c:3540可以通过下面的SQL复现该问题,通过构造一个没有终止条件的递归函数,使backend调用栈用满,从而触发stack depth limit exceeded
CREATEORREPLACEFUNCTIONrecurse(nint)RETURNSintLANGUAGEplpgsqlAS$$BEGINRETURNrecurse(n+1);END;$$;SELECTrecurse(1);问题原因
max_stack_depth 是 HGDB用于限制单个 backend 进程可用调用栈深度的参数。当执行以下对象时,进程会消耗栈空间:
- SQL 表达式
- 存储过程、函数
- 触发器、规则
- 复杂嵌套查询、递归 CTE
若调用链持续增长而无合理终止条件,backend 进程将不断逼近操作系统允许的栈空间上限。HGDB 通过主动栈深度检查机制在达到阈值时中止语句并报错,从而避免栈空间被彻底耗尽导致进程异常。
常见触发场景
- 递归函数缺少终止条件或终止条件永远无法满足(直接递归)
- 多个函数、视图、规则、触发器之间形成循环调用链(间接递归)
- 触发器在 DML 过程中再次触发本表或关联表的逻辑,形成嵌套执行链
- 业务 SQL 动态拼接复杂表达式或嵌套函数调用,调用深度异常增加
解决方案
临时方案
通过调整 max_stack_depth 参数,增加backend堆栈最大深度。
检查操作系统栈大小:ulimit -s(单位 kB)
查看当前数据库参数:SHOW max_stack_depth;
评估安全余量,确保 max_stack_depth 显著小于 OS 栈大小
修改参数值,可以根据数据库承载的业务判断修改参数的作用域
session: 在会话中使用 SET max_stack_depth = ‘新值’;,直接生效,对当前会话生效。
user: 执行 ALTER USER username SET max_stack_depth = ‘新值’; 修改,直接生效,对指定用户生效。
database: 执行 ALTER DATABASE dbname SET max_stack_depth = ‘新值’;修改,直接生效,对指定 database 生效。
全局: 执行 ALTER SYSTEM SET max_stack_depth = ‘新值’; 修改, 通过执行 SELECT pg_reload_conf(); 生效,作用整个HGDB实例。
复测相关 SQL、函数或批处理任务,确认问题不再重现。
报错编码
54001
