循环调用PostgreSQL存储过程异常:CPU占满超时问题排查
问题描述
编写了如下PostgreSQL存储过程insert_into_tableAv2,用于从tableA批量插入100条未存在于tableAv2的记录:
CREATE OR REPLACE PROCEDURE insert_into_tableAv2(inout rows_affected INT) LANGUAGE 'plpgsql' AS $$ BEGIN INSERT INTO insert_into_tableAv2 (serial, aaa, ooo, UPDATED) SELECT id, aaa, ooo, UPDATED FROM tableA WHERE NOT EXISTS ( SELECT 1 FROM tableAv2 WHERE tableA.id = tableAv2.serial AND tableA.aaa = tableAv2.aaa ) LIMIT 100; GET DIAGNOSTICS rows_affected = ROW_COUNT; RETURN; END; $$;
DEV环境中tableA仅含9000条数据,属于小型表,但通过如下DO块循环调用该存储过程时,出现RDS CPU占用100%、无法插入且超时的问题:
DO $$ DECLARE result int := 0; -- Initialize with a starting value BEGIN LOOP result := 0; -- Call the procedure and update the result CALL insert_into_tableAv2(result); -- Exit the loop if the result is 0 EXIT WHEN result = 0; END LOOP; END $$;
该存储过程是为后续在更大表中执行类似批量操作编写的,请问调用异常的原因是什么?
异常原因分析
- 存储过程插入目标表错误:存储过程里的
INSERT INTO insert_into_tableAv2 (...)写错了目标表,应该是tableAv2却写成了存储过程自身的名称。这会导致每次调用时尝试往错误的对象插入数据,触发大量无效操作或异常,直接拉高CPU占用。 - 缺失索引引发重复全表扫描:
tableAv2未创建(serial, aaa)复合索引,每次执行NOT EXISTS子查询时都会对tableAv2做全表扫描。循环调用时,随着tableAv2数据量增加,全表扫描的开销持续累积,即使小型表也会很快导致CPU饱和。 - 循环无间隔持续施压:DO块的循环是不间断执行的,没有任何延迟或合理的事务控制,数据库被持续的批量请求占满资源,进一步加剧CPU负载。
内容的提问来源于stack exchange,提问作者ahmet gül
相关产品推荐
相关产品推荐

