ORA-01000: 超出打开游标的最大数(解决及缘由)

仍是 chongqingdaxue 缴费平台, 税票打印完毕, 上传到财务处时, 当税票数目较少时(10几张), 能正常上传; 当数目较大时(408), 就上传失败. 查看 tomcat 日志, 以下:html

clip_image001[4]

既然超出最大游标数, 为了第一间让程序恢复正常运行, 固然"脚疼治脚", 先把最大游标数调大:java

(1). DBA 登陆 PL/SQLsql

(2). 打开 Command Window(注意不是 SQL Window)数据库

clip_image002[4]

(3). 输入如下命令, 修改 oracle 最大游标数为 1000tomcat

SQL> alter system set open_cursors=1000 scope=both;

(4). 查看最大游标数是否已修改为功oracle

SQL> show parameter open_cursors;

(5). 重启 tomcat(必定要有这一步, 不然修改不生效)函数

 

通过以上操做, 票据顺利上传上去了, 但是这样治标不治本, 万一之后来个1000张以上的票据要上传, 那不就又得改游标数了; 在代码里确定是每处理一张票就打开一个游标的, 这样是错误的. 网上找了这个错误代码的相关说明, 在这里发现如下这段话post

这样的错误很容易出如今Java代码中的主要缘由是:Java代码在执行conn.createStatement()和 conn.prepareStatement()的时候,实际上都是至关与在数据库中打开了一个cursor。尤为是,若是你的 createStatement和prepareStatement是在一个循环里面的话,就会很是容易出现这个问题。由于游标一直在不停的打开,并且没有关闭。


在代码里看了一下, 果真是这样, 程序经过循环调用封装好的 executeSql 函数, 来对每张票进行 update, 而 executeSql 里每次都调用了 conn.prepareStatement(); 将其移出循环, 再改回原游标数, 再上传票据, 就再也不报错了.大数据

public static void executeSql(Connection conn, String sql, Object[] parValue) throws Exception{
	PreparedStatement ps = null;
	try {
		LOGGER.info(sql);
		ps = conn.prepareStatement(sql);
		if (parValue != null){
			String params = "";
			for (int i = 0; i < parValue.length; i++){
				if (i != 0){
					params += ",";
				}
				ps.setObject(i+1, parValue[i]);
				params += parValue[i];
			}
			LOGGER.info(params);
		}
		ps.execute();
	} catch (SQLException e) {
		e.printStackTrace();
		throw new Exception();
	} finally {
		if (ps != null){
			ps.close();
		}
	}
}

注: 原代码有进行 ps.close(); , 可是仍然无效, 是由于 connection 的 autocommit 设为 false 的缘由? 仍是由于 connection 是从链接池取的缘由呢? spa

这里有一个问题说明 connection 与 prepareStatement 进行 close 的关系, 但这里只是说明了直接 close connection, 而没有说明直接 close prepareStatement.

问:

用CONNECTION 建立了 PREPAREDSTATEMENT ,用完了 PREPAREDSTATEMENT 后,没有关闭PREPAREDSTATEMENT ,而是直接 CLOSE CONNECTION ,这么作有什么隐患吗?

答:

若是没有使用数据库链接池,而是每次建立物理链接,而后释放的话,没有什么问题。close Connection的时候已经把数据库资源彻底释放掉了,PreparedStatement占用的数据库游标也会随即释放。 可是大部分状况读写数据库都会采用数据库链接池来提升链接效率,在这种状况下有潜在的隐患。 由于数据库链接池中拿到一个Connection,close的时候不是真正关闭链接,释放数据库资源,而是把链接归还给链接池。所以在这种状况下,close了Connection,可是PreparedStatement并无被释放掉,占用的数据库游标仍然处于打开状态。所以在大数据访问量的状况下很容易出现数据库游标使用到最大,没法分配游标错误。


 环境: Oracle 10g

相关文章
相关标签/搜索