名字起的好拗口。
这是一个关于执行超时的问题。
业务场景是这样的:根据要求,需要每天生成若干报表(原始数据量约为4-5GB),使用一个总的存储过程调度几十个子存储过程(由于有依赖关系,存储过程需要串行执行),为了不影响当天的剩下的工作,生成报表有个容忍时间(2-3小时),超过时间后就需要强行终止。
在测试中发现,使用setQueryTimeout()方法,或者cancel()方法,超时后存储过程确实终止了,并且在记录中可以看到“ORA-01013: 用户请求取消当前的操作”这个异常,但是下面再执行其他的SQL语句(简单的查询),在java端却也爆出了这个错误,导致该SQL执行出错,而且查看日志可以看到,爆出错误的链接(oracle.jdbc.driver.T4CConnection)和执行存储过程的链接是同一个,其他的连接就没问题。
以上问题不管用最原始的JDBC,c3p0连接池还是用SpringJdbcTemplate,还是更新OJDBC驱动,都无法解决(数据库是Oracle10),最后折腾了半天也没发现是怎么回事。
存储过程如下,模拟长时间执行:
create or replace procedure pro_test is
err_msg varchar2(4000);
begin
for i in 1..60
loop
insert into scott.prolog(id,date, info)values(i, sysdate,'222');
DBMS_LOCK.sleep(1);
commit;
end loop;
exception
when others then
err_msg := sqlerrm;
rollback;
insert into scott.prolog(id,date, info)values('err', sysdate,err_msg);
commit;
return;
end;
异常在存储过程中捕获,并进行记录,然后直接返回,但这种方式JDBC端察觉不到任何异常。
最后,尝试在return之前抛出异常,利用下面的语句:
RAISE_APPLICATION_ERROR(-22222, '系统异常');
return;
然后,超时后JDBC可以捕获到-22222的SQLException,而且再用相同的链接执行任意SQL也不再报错了。
具体什么原因导致了这种情况不得而知,暂且记录一下。盼望有高手解答。