在JPA中调用存储过程并及时将资源释放
问题
最近发现在调用某个API执行batch job(批处理)时,每当数据量达到一定数量时,后续的记录都会出现以下错误:
oracle ORA-01000: maximum open cursors exceeded
原因
- 排查发现该batch job中包含调用存储过程的逻辑,并且未释放资源
这就导致了在一个事务中处理多条记录时开启了多个游标而未关闭,导致游标数激增 - 而在单个用户日常使用的场景,往往都是一个事务中处理单条记录或少量记录,在 事务完成 后,数据库会 自动关闭 这期间开启的游标,所以在用户日常使用时,这个问题没有被发现
SQL
查看当前打开的游标数目:
select count(*) from v$open_cursor;
完整示例代码
public void test(String id) {
StoredProcedureQuery procedureQuery = em.createStoredProcedureQuery("TEST_PKG.test");
try{
procedureQuery.registerStoredProcedureParameter("p_id", String.class, ParameterMode.IN);
procedureQuery.setParameter("p_id", id);
procedureQuery.execute();
}finally {
procedureQuery.unwrap(ProcedureOutputs.class).release();
}
}
关闭资源的语句:
procedureQuery.unwrap(ProcedureOutputs.class).release();
注意点
- 无论调用存储过程是否成功,必须将资源释放,避免资源占用导致出现问题或影响其他数据库操作
- 注意区分日常用户使用的场景和批处理的场景的区别,能够更好的分析排查BUG原因