jstack 21455 > /tmp/t.txt grep -A 20 'StackOverflowError' /tmp/t.txt | head -25 WITH RECURSIVE t AS (SELECT id,parent_id,1 d FROM dept WHERE id=8801 UNION ALL SELECT d.id,d.parent_id,t.d+1 FROM dept d JOIN t ON d.parent_id=t.id WHERE t.d<60) SELECT * FROM t;
组织架构接口报 500,日志最后是 java.lang.StackOverflowError,堆栈前 20 行全是 OrgService.findChildren,请求参数里的部门 id 指向一条循环引用。先别急着动参数,把报错原文和时间点记下来,顺序反了容易白折腾。
原因不复杂,部门表里 A 的父级被改成了自己的下级,递归没有深度上限也没有 visited 集合,沿着环一直调用到栈满。默认 1MB 栈大约一万多层就到底。
「递归栈溢出」改完先别急着全量,挑一台机器放半天,真有问题这段时间就能看出来。备份不是备了就行,恢复一次才算数,很多备份文件打开才发现是空的。
接口问题先分清是没发出去、发出去了没收到,还是收到了处理失败。
处理上按这个顺序:先按报错栈顶的方法名找到递归入口;查数据里的 parent_id 环 把脏数据修掉;代码里加 visited 集合 遇到已访问节点直接返回;保留深度上限 超过 50 层记录告警而不是继续递归。
改完只确认一件事:同一部门 id 再查返回 200 堆栈里不再出现 StackOverflowError 环上的数据被修正。
