Oracle运维日记

前言

最近实验室一直的一个运维项目频频在Oracle上出错,想着错误还挺典型,做一个记录,以供后续参考学习使用。 

运维记录

1. ORA-01000: 超出打开游标的最大数

问题描述:需要开多进程遍历对象集合,并且将对象数据存入到Oracle数据库中,测试报超出Oracle游标最大数的错误。

知识介绍:

Oracle的游标数cursors:游标是SQL的一个内存工作区,由系统或用户以变量的形式定义。游标的作用就是用于临时存储从数据库中提取的数据块。在某些情况下,需要把数据从存放在磁盘的表中调到计算机内存中进行处理,最后将处理结果显示出来或最终写回数据库。这样数据处理的速度才会提高,否则频繁的磁盘数据交换会降低效率。(参考https://www.cnblogs.com/guohu/p/11007352.html

游标一旦打开,数据就从数据库中传送到游标变量中,然后应用程序再从游标变量中分解出需要的数据,并进行处理

一般Oracle默认游标数OPNE_CURSORS为300(足以够用),最大为1000

解决方法:

1. 手动在Oracle中增大游标数

//查看系统配置游标数法1
select value from v$parameter where name = 'open_cursors';
//查看系统配置游标数法2
show parameter open_cursors;

//查看当前被打开的游标个数
select count(*) from v$open_cursor;

//修改Oracle游标数
alter system set open_cursors=1000 scope=both;

2. 程序中及时释放资源,这里需要明确一般释放的顺序是ResultSet(如果用到的话)、PreparedStatement、Connection。

如果没有释放prepareStament就关闭了connection,虽然看起来是释放了资源,但是游标数并没有得到释放,如果数据量请求量特别大的情况下,每次请求都没有释放游标数,就有可能导致最终Oracle提供的游标数被占满从而报ORA-01000的错误。

参考https://blog.csdn.net/wodestudy/article/details/23887279?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

一般有的可能有二:

1) 关闭Connection(将连接放入连接池)前未关闭PreparedStatement(即游标)

2) 在循环体中使用connection.prepareStatement(sql)初始化preparedStatement对象后,未在循环体执行完增/删/改/查后及时关闭到PreparedStatement,导致数据量过大的时候游标不够用

for(int i = 0; i < vos.size(); i++){
    preparedStatement = connnection.prepareStatement(sql);
    preparedStatement.setString(1,vos.getXXX());
    preparedStatement.setString(2,vos.getXXX());
    preparedStatement.setString(3,vos.getXXX());
    preparedStatment.executeUpdate();
    //打开游标后使用完及时关闭
    if(preparedStatement != null){
        prepatedStatemnet.close();
    }
}

此处需要注意的是将程序修改为及时关闭游标,但是在多进程并发执行的过程中还是有可能出现ORA-01000的错误,这是因为oracle给的游标数就是那么大,如果当前进程数比较大所有的游标数都被占了,那么在有游标被释放前会有一段时间资源被用完线程无法执行,等待有游标可用时即可继续执行。

总结

以问题为索引,不断学习,不断进步。

发布了41 篇原创文章 · 获赞 9 · 访问量 9755

猜你喜欢

转载自blog.csdn.net/qq_38586378/article/details/104777983