在使用hibernate5 与 druid 时候,开发机器都不存在问题,而在测试的时候出现了ORA-01000: maximum open cursors exceeded 的错误.
在查询之后发现,不是因为
ava代码在执行conn.createStatement()和conn.prepareStatement()的时候,实际上都是相当与在数据库中打开了一个cursor。尤其是,如果你的createStatement和prepareStatement是在一个循环里面的话,就会非常容易出现这个问题。因为游标一直在不停的打开,而且没有关闭。
的问题。
仔细分析后 发现是因为系统启动的时候默认开启了hibernate 更新表结构的配置。
我们业务系统的表多大近400张表,hibernate会进行大量的查询与更新.这时候就会出现如上所说的问题.
因为hibernate session的方式,都是通过ThreadLocal来的,并且确认会在数据库操作完成之后,在finally中执行Session.close()。但是 在close的时候,并不会按照jdbc的规范去做,它只是回到连接池,而不是真正关闭。所以执行Session.close后,但是Statement没有被同时关闭,而且因为仍然被应用也不会被gc,长时间运行就会造成游标过大。
hibernate官方已有类似问题。
Q:After a while, Oracle throws this exception: too many open cursors
A:The Oracle JDBC driver doesn’t much like to have its prepared statements cached. Disable PreparedStatement caching for the connection pool.
方式一: 也就是关闭连接池的PreparedStatement。
在druid 的情况下,默认是推荐oracle打开,mysql关闭的.
druid poolPreparedStatements 参数解释如下:
是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
方式二:增大数据库游标大小. 这种方式还在具体测试中,是否能真正的解决问题。
Oracle中默认游标最大值是300,增大操作如下:
sqlplus /nolog
SQL>conn /as sysdba
SQL>show parameter open_cursors;
SQL>alter system set open_cursors=1200 scope=both;