OracleDataSource与Oracle UCP PoolDataSource
我正在研究一些JDBC Oracle连接池项目,并遇到了一个名为Universal Connection Pool(UCP)的新的Oracle池实现。 现在,它使用一个新类PoolDataSource用于连接池,而不是OracleDataSource [启用caching选项]。 我正在辩论是否切换到这个新的实现,但找不到任何(如果有的话)修复/升级,这将会给我买的任何好的文档。 任何人都有这两个经验? 加号/劣势? 谢谢。
最新的Oracle jdbc驱动程序(11.2.0.1.0)明确指出,Oracle隐式连接caching(即使用OracleDataSource的那个)不推荐使用:
Oracle JDBC驱动程序版本11.2.0.1.0生成Readme.txt
这个版本有什么新东西?
通用连接池在此版本中,不build议使用Oracle隐式连接cachingfunction。 强烈build议用户改用新的Universal Connection Pool。 UCP拥有ICC的所有function,还有更多function。 UCP在单独的jar文件ucp.jar中可用。
所以我认为开始使用UCP会更好,但是文档并不是那么好。 例如,我没有find一种方法来使用弹簧UCP …
更新:我已经find了正确的弹簧configuration:好吧,我想我find了正确的configuration:
<bean id="dataSource" class="oracle.ucp.jdbc.PoolDataSourceFactory" factory-method="getPoolDataSource"> <property name="URL" value="jdbc:oracle:thin:@myserver:1521:mysid" /> <property name="user" value="myuser" /> <property name="password" value="mypassword" /> <property name="connectionFactoryClassName" value="oracle.jdbc.pool.OracleDataSource" /> <property name="connectionPoolName" value="ANAG_POOL" /> <property name="minPoolSize" value="5" /> <property name="maxPoolSize" value="10" /> <property name="initialPoolSize" value="5" /> <property name="inactiveConnectionTimeout" value="120" /> <property name="validateConnectionOnBorrow" value="true" /> <property name="maxStatements" value="10" /> </bean>
关键是要指定正确的工厂类和正确的工厂方法
PDS是“通用的”,因为它提供了与非Oracle数据库(例如MySQL)ODS相同的池化function。
请参阅UCP开发指南 ,这是一个关于Oracle网站和UCP过渡指南的文章
我没有看到从ODS转向UCP(PDS)的直接好处,但也许将来Oracle可能会贬低ODS中的一些function。 我用了一段时间的ODS,现在我对它很满意,但是如果我开始新鲜,我会用PDS。
我做了广泛的UCP评估,并决定不使用UCP – 请看看这个职位的细节。
我testing了UCP并将其部署到使用Spring JMS侦听器容器和Springpipe理的会话和使用@Transactional注释的事务的Spring 3.0.5 Hibernate应用程序中。 数据有时会导致SQL约束错误,因为单独的侦听器线程试图更新相同的logging。 当发生这种情况时,通过@Transactional注释的方法抛出exception,并使用由@Transactional注释的另一种方法将错误logging到数据库中。 无论出于何种原因,这个过程似乎导致游标泄漏,最终加起来并触发ORA-01000打开游标限制超出错误,导致线程停止处理任何东西。
运行在相同代码中的OracleDataSource似乎不会泄漏游标,因此不会导致此问题。
这是一个非常奇怪的场景,但是它表明,在这种结构的应用程序中使用UCP有点太早了。
我也在testingUCP,发现自己在基于线程池的应用程序中遇到性能问题。 最初,我尝试了OracleDataSource,但在configuration批处理时遇到了麻烦。 我一直在连接中得到NullPointerExceptions,导致我认为我有一些sorting连接泄漏,但只有在某些应用程序中,我们pipe理的其他应用程序不是批处理stream程导向的,OracleDataSource运行良好。
基于这个职位和其他一些我发现研究这个问题,我试过UCP。 我发现,经过足够的调整,我可以摆脱连接样式错误的closures连接/ NullPointerExceptions,但垃圾收集正在殴打。 长期的GC填充速度很快,在应用程序运行完成之前,似乎没有空闲。 如果负载真的很重,有时可能需要一天或更长的时间。 我也注意到,处理数据也需要更长的时间。 我将它与现在已经折旧的OracleCacheImpl类(我们目前在生产中使用,因为它仍然“正常工作”)进行比较,它使用了UCP处理文件的三分之一,并且更快地处理文件。 在所有其他的应用程序中,UCP似乎工作得很好,并处理了我所投的一切,但是线程池应用程序是一个主要的应用程序,我不能在生产中冒险处理GCexception。
我试过ucp和性能更好…可能是关键是使用这个
oracle.ucp.jdbc.PoolDataSource ds = (oracle.ucp.jdbc.PoolDataSource)envContext.lookup(url_r); MyConnectionLabelingCallback callback = new MyConnectionLabelingCallback(); ds.registerConnectionLabelingCallback( callback ); Properties label = new Properties(); label.setProperty(pname, KEY); conn = ds.getConnection(label);
这有助于借用连接,而不会closures它,所以性能很好
callback类的代码是
公共类MyConnectionLabelingCallback实现ConnectionLabelingCallback {
public MyConnectionLabelingCallback() { } public int cost(Properties reqLabels, Properties currentLabels) { // Case 1: exact match if (reqLabels.equals(currentLabels)) { System.out.println("## Exact match found!! ##"); return 0; } // Case 2: some labels match with no unmatched labels String iso1 = (String) reqLabels.get("TRANSACTION_ISOLATION"); String iso2 = (String) currentLabels.get("TRANSACTION_ISOLATION"); boolean match = (iso1 != null && iso2 != null && iso1.equalsIgnoreCase(iso2)); Set rKeys = reqLabels.keySet(); Set cKeys = currentLabels.keySet(); if (match && rKeys.containsAll(cKeys)) { System.out.println("## Partial match found!! ##"); return 10; } // No label matches to application's preference. // Do not choose this connection. System.out.println("## No match found!! ##"); return Integer.MAX_VALUE; } public boolean configure(Properties reqLabels, Object conn) { System.out.println("Configure################"); try { String isoStr = (String) reqLabels.get("TRANSACTION_ISOLATION"); ((Connection)conn).setTransactionIsolation(Integer.valueOf(isoStr)); LabelableConnection lconn = (LabelableConnection) conn; // Find the unmatched labels on this connection Properties unmatchedLabels = lconn.getUnmatchedConnectionLabels(reqLabels); // Apply each label <key,value> in unmatchedLabels to conn for (Map.Entry<Object, Object> label : unmatchedLabels.entrySet()) { String key = (String) label.getKey(); String value = (String) label.getValue(); lconn.applyConnectionLabel(key, value); } } catch (Exception exc) { return false; } return true; } }
Spring Bean.xml中有两种使用UCP的方法。
对于由某个文件设置的db.properties,然后加载这个然后使用其中之一:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location"> <value>classpath:resources/db.properties</value> </property> </bean>
第一个与oracle.ucp.jdbc.PoolDataSourceImpl: –
<bean id="dataSource" class="oracle.ucp.jdbc.PoolDataSourceImpl"> <property name="URL" value="${jdbc.url}" /> <property name="user" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="validateConnectionOnBorrow" value="true"/> <property name="connectionFactoryClassName" value="oracle.jdbc.pool.OracleDataSource" /> <property name="connectionPoolName" value="TEST_POOL" /> <property name="minPoolSize" value="10" /> <property name="maxPoolSize" value="20" /> <property name="initialPoolSize" value="12" /> </bean>
第二个与oracle.ucp.jdbc.PoolDataSourceFactory: –
<bean id="dataSource" class="oracle.ucp.jdbc.PoolDataSourceFactory" factory-method="getPoolDataSource"> <property name="URL" value="${jdbc.url}" /> <property name="user" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="validateConnectionOnBorrow" value="true"/> <property name="connectionFactoryClassName" value="oracle.jdbc.pool.OracleDataSource" /> <property name="connectionPoolName" value="TEST_POOL" /> <property name="minPoolSize" value="10" /> <property name="maxPoolSize" value="20" /> <property name="initialPoolSize" value="12" /> </bean>
就是这样:)以下是详细资料文档的链接: https : //docs.oracle.com/cd/E11882_01/java.112/e12265/connect.htm#CHDDCICA
如果使用连接validation,则隐式连接caching比UCP执行得好一些。 这对应于bug 16723836,它被安排在12.1.0.2中被修复。
随着并发负载的增加,UCP池的获取/返回连接变得越来越昂贵。 testing比较了oracle隐式连接caching,tomcat的池和UCP。 所有3个configuration允许最多200个连接,最less20个连接和一个初始大小2.所有3个configuration为validation从池中删除的连接。 tomcat池使用语句“select dual from dual”进行validation。
这些结果在具有64个逻辑核心(32个物理)和128个RAM的64位RedHat节点上进行。
在5个并发线程中,UCP是最慢的,但总连接pipe理时间(get和close)平均在1 ms以下。 随着并发性的增加,UCP进一步落后于其他解决scheme:
25 Threads: Implicit: 0.58ms Tomcat: 0.92ms UCP: 1.50ms 50 Threads: Implicit: 0.92ms Tomcat: 1.60ms UCP: 6.80ms 100 Threads: Implicit: 2.60ms Tomcat: 3.20ms UCP: 21.40ms 180 Threads: Implicit: 13.86ms Tomcat: 15.34ms UCP: 40.70ms