package com.cafe.test;import java.sql.*;
class Test{
/**
* @param args
*/
/**
* @param args
*/
public static void main(String args[])
{
int i=0;
String RL = "jdbc:oracle:thin:@localhost:1521:orcl";
String user ="cafe";//这里替换成你自已的数据库用户名
String password = "pwd";//这里替换成你自已的数据库用户密码
String sqlStr = "select * from main_info"; try{ //这里的异常处理语句是必需的.否则不能通过编译!
Class.forName("oracle.jdbc.driver.OracleDriver");
System.out.println( "类实例化成功!" );
Connection con = DriverManager.getConnection(RL,user,password);
System.out.println( "创建连接对像成功!" ); Statement st = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
System.out.println( "创建Statement成功!" ); //st.setMaxRows(10);
ResultSet rs = st.executeQuery( sqlStr );
System.out.println( "操作数据表成功!" );
System.out.println( "----------------!" );
System.out.println("FetchSize:"+rs.getFetchSize());
//测试结果集是否支持滚动 while(rs.next())
{
i=i+1;
}
System.out.println(i);
rs.close();
st.close();
con.close();
}
catch(Exception err){
err.printStackTrace(System.out);
}
}
}结果:
类实例化成功!
创建连接对像成功!
创建Statement成功!
操作数据表成功!
----------------!
FetchSize:10
Result set is scrollable
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at oracle.jdbc.driver.CharCommonAccessor.getBytes(CharCommonAccessor.java:491)
at oracle.jdbc.driver.OracleResultSetImpl.getBytes(OracleResultSetImpl.java:641)
at oracle.jdbc.driver.ScrollableResultSet.cacheRowAt(ScrollableResultSet.java:1461)
at oracle.jdbc.driver.ScrollableResultSet.isValidRow(ScrollableResultSet.java:1441)
at oracle.jdbc.driver.ScrollableResultSet.absolute(ScrollableResultSet.java:385)
at com.cafe.test.Test.main(Test.java:43)我的数据库中有百万以上的数据。如何解决内存溢出的问题。按理说getfetch得到的是10,说明resultSet每次更新10行,不应该内存溢出啊。
class Test{
/**
* @param args
*/
/**
* @param args
*/
public static void main(String args[])
{
int i=0;
String RL = "jdbc:oracle:thin:@localhost:1521:orcl";
String user ="cafe";//这里替换成你自已的数据库用户名
String password = "pwd";//这里替换成你自已的数据库用户密码
String sqlStr = "select * from main_info"; try{ //这里的异常处理语句是必需的.否则不能通过编译!
Class.forName("oracle.jdbc.driver.OracleDriver");
System.out.println( "类实例化成功!" );
Connection con = DriverManager.getConnection(RL,user,password);
System.out.println( "创建连接对像成功!" ); Statement st = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
System.out.println( "创建Statement成功!" ); //st.setMaxRows(10);
ResultSet rs = st.executeQuery( sqlStr );
System.out.println( "操作数据表成功!" );
System.out.println( "----------------!" );
System.out.println("FetchSize:"+rs.getFetchSize());
//测试结果集是否支持滚动 while(rs.next())
{
i=i+1;
}
System.out.println(i);
rs.close();
st.close();
con.close();
}
catch(Exception err){
err.printStackTrace(System.out);
}
}
}结果:
类实例化成功!
创建连接对像成功!
创建Statement成功!
操作数据表成功!
----------------!
FetchSize:10
Result set is scrollable
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at oracle.jdbc.driver.CharCommonAccessor.getBytes(CharCommonAccessor.java:491)
at oracle.jdbc.driver.OracleResultSetImpl.getBytes(OracleResultSetImpl.java:641)
at oracle.jdbc.driver.ScrollableResultSet.cacheRowAt(ScrollableResultSet.java:1461)
at oracle.jdbc.driver.ScrollableResultSet.isValidRow(ScrollableResultSet.java:1441)
at oracle.jdbc.driver.ScrollableResultSet.absolute(ScrollableResultSet.java:385)
at com.cafe.test.Test.main(Test.java:43)我的数据库中有百万以上的数据。如何解决内存溢出的问题。按理说getfetch得到的是10,说明resultSet每次更新10行,不应该内存溢出啊。
finally{
rs.close();
st.close();
con.close();
}
这个问题的根源是jvm虚拟机的默认Heap大小是64M,可以通过设置其最大和最小值来实现.设置的方法主要是几个.
1.可以在windows 更改系统环境变量
加上JAVA_OPTS=-Xms64m -Xmx512m
2,如果用的tomcat,在windows下,可以在
C:\tomcat5.5.9\bin\catalina.bat 中加上:
set JAVA_OPTS=-Xms64m -Xmx256m
位置在: rem Guess CATALINA_HOME if not defined 这行的下面加合适.
3.如果是linux系统
Linux 在{tomcat_home}/bin/catalina.sh的前面,加
set JAVA_OPTS='-Xms64 -Xmx512'
具体做法要根据你的web容器来定。百度上可以找到正确的配置方法。
如果是查询,可以用over()排序+ rownum分页;
如果是一次全部更新,最好用存储过程来做。不论存储过程还是java代码,最好一次更新不要太多条,如果数据库的回滚空间设置不大或者服务器本身性能不咋的,数据库会出现 回滚日志全部占满的错误或服务器当掉。比如你100万要全部更新,你就1万1万的commit。当然如果你说要么全部更新要么全部不更新,那我也不知道怎么办了
2楼说的是jdbc释放连接的标准做法。否则你出错连接不关闭,你的应用很快就会当掉。
rs.close();
st.close();
con.close();
}
这个不能解决问题,现在程序还没有执行到要关闭的时候呢,现在程序是在rs.next()这就出现内存溢出了,问题出在数据库里的数据量太大,java把这些数据取出来放在内存里,用过的数据后没有释放。程序的逻辑还没要轮到最终释放连接句柄这一步骤呢。
你可以用Eclipse analyzer分析一下
你不想多次连接数据库,可以采用连接保持,CallableStatement 或PreparedStatement 来获取一段一段的数据,用完关闭resultset的方法来做。
select * from main_info rownum>=N and rownum<M
用循环分别代替那两个参数~ 避免以下导出数据过多~
st = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
改成
Statement st = con.createStatement();就没有出现内存溢出的异常.
莫非可滚动的结果集会把所有的数据取到内存里,而普通的结果集就回按fetchsize设置的值取,每次取出的数据都会覆盖原来的数据? 有没有高人,懂这里的内部机制的?
ResultSet.CONCUR_READ_ONLY);
你让它支持scroll,所以它保存了中间结果……把ResultSet.TYPE_SCROLL_SENSITIVE改称ResultSet.TYPE_FORWARD_ONLY就可以了,
这样游标resultset不能会滚,内存得以释放。1.TYPE_FORWORD_ONLY,只可向前滚动;2.TYPE_SCROLL_INSENSITIVE,双向滚动,但不及时更新,就是如果数据库里的数据修改过,并不在ResultSet中反应出来。3.TYPE_SCROLL_SENSITIVE,双向滚动,并及时跟踪数据库的更新,以便更改ResultSet中的数据。
Statement st = con.createStatement(
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY);