OracleDataSource与Oracle UCP PoolDataSource

时间:2009-09-15 15:29:58

标签: oracle jdbc

我正在研究一些JDBC Oracle连接池项目,并遇到了一个名为通用连接池(UCP)的新的(Oracle)Oracle池实现。现在,它使用一个新类PoolDataSource用于连接池,而不是OracleDataSource [启用了缓存选项]。我正在讨论是否要切换到这个新的实现,但找不到任何关于修复/升级这些会给我带来什么(如果有的话)的好文档。有人都有经验吗?加号/劣势?感谢。

8 个答案:

答案 0 :(得分:32)

最新的Oracle jdbc驱动程序(11.2.0.1.0)显式声明Oracle Implicit Connection缓存(使用OracleDataSource的缓存)已被弃用:

  

Oracle JDBC驱动程序发布11.2.0.1.0生产Readme.txt

     

此版本中有哪些新内容?

     

通用连接池      在此版本中,Oracle隐式连接缓存功能是      弃用。强烈建议用户使用新的Universal      而是连接池。 UCP具有的所有功能      国际刑事法院,还有更多。 UCP可以在单独的jar文件中找到,      ucp.jar。

所以我认为最好开始使用UCP,但文档并不是那么好。 例如,我没有找到一种方法来使用UCP和弹簧...

更新:我找到了正确的弹簧配置: 好的,我想我找到了正确的配置:

<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>

关键是指定正确的工厂类和正确的工厂方法

答案 1 :(得分:9)

PDS是“通用的”,因为它为非Oracle数据库提供了与ODS相同的池化功能,例如,的MySQL。

请参阅UCP Dev Guidean article on Oracle websiteUCP Transition Guide

我没有看到从ODS迁移到UCP(PDS)的任何直接好处,但是将来Oracle可能会弃用ODS中的一些功能。我暂时使用了ODS,暂时对它很满意,但如果我开始新的,我会选择PDS。

答案 2 :(得分:4)

我对UCP进行了广泛的评估,并决定不使用UCP - please have a look at this post来获取详细信息。

答案 3 :(得分:3)

我测试了UCP,并使用Spring JMS监听器容器和使用@Transactional注释的Spring管理会话和事务,在Spring 3.0.5 Hibernate应用程序中将其部署到生产环境中。由于单独的侦听器线程尝试更新同一记录,因此数据有时会导致SQL约束错误。发生这种情况时,由@Transactional注释的一个方法抛出异常,并使用@Transactional注释的另一个方法将错误记录到数据库中。无论出于何种原因,此过程似乎导致游标泄漏,最终会加起来并触发ORA-01000开放游标限制超出错误,导致线程停止处理任何内容。

运行相同代码的OracleDataSource似乎没有泄漏游标,因此不会导致此问题。

这是一个非常奇怪的场景,但它向我表明,在具有这种结构的应用程序中使用UCP还为时尚早。

答案 4 :(得分:3)

我也在测试UCP,并且发现自己在基于线程池的应用程序中遇到了性能问题。最初,我尝试了OracleDataSource,但是在配置它进行批处理时遇到了问题。我一直在连接中得到NullPointerExceptions,这让我相信我有一些排序连接泄漏,但只有一些应用程序,我们管理的其他应用程序不是面向批处理过程的OracleDataSource运行良好。

基于这篇文章和其他一些我发现研究这个主题,我尝试了UCP。我发现通过足够的调整,我可以摆脱连接样式错误的关闭连接/ NullPointerExceptions,但垃圾收集正在受到打击。长期GC快速填满,并且在应用程序完成运行之前似乎永远不会释放。如果负载非常重,有时可能需要一天或更长时间。我还注意到,处理数据也需要更长的时间。我将它与现在已经折旧的OracleCacheImpl类(我们目前在生产中使用,因为它仍然“正常工作”)相比较,它使用了UCP所做的三分之一的GC内存并更快地处理文件。在所有其他应用程序中,UCP似乎工作得很好并处理我所投入的所有内容,但是线程池应用程序是一个主要的应用程序,我不能冒生产中的GC Exceptions。

答案 5 :(得分:2)

如果使用连接验证,隐式连接缓存比UCP执行得更好。这对应于错误16723836,计划在12.1.0.2中修复。

UCP池的获取/返回变得越来越昂贵 连接负载增加时的连接。测试比较了oracle 隐式连接缓存,tomcat的池和UCP。所有3个都是 配置为允许最多200个连接,至少20个连接和 初始大小为2.所有3都配置为验证连接为 他们被从池中删除。 tomcat池使用语句“select sysdate来自双重“用于验证。

这些结果在64位RedHat节点上,具有64个逻辑核心(32个物理核心)和128 GB RAM。

在5个并发线程中,UCP是最慢但总连接管理 时间(获取和关闭)平均低于1毫秒。 随着并发性的增加,UCP越来越落后于 其他解决方案:

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

答案 6 :(得分:0)

我试过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);

这有助于借用连接并且永远不会关闭它。所以性能很好

回调类的代码是

public class MyConnectionLabelingCallback
implements 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;
      }
    }

答案 7 :(得分:0)

在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