OracleDataSource против Oracle UCP PoolDataSource - PullRequest
37 голосов
/ 15 сентября 2009

Я исследовал некоторые элементы JDBC Oracle Connection Pooling и наткнулся на новую реализацию Oracle Pool, которая называется Universal Connection Pool (UCP). Теперь для пула соединений используется новый класс PoolDataSource, а не OracleDataSource [с включенной опцией кэширования]. Я спорю о том, стоит ли переходить на эту новую реализацию, но я не могу найти хорошую документацию о том, что (если таковые имеются) исправления / обновления это купит мне. У кого-нибудь есть опыт работы с обоими? Плюсы / минусы? Спасибо.

Ответы [ 8 ]

32 голосов
/ 17 сентября 2009

В последнем драйвере Oracle jdbc (11.2.0.1.0) явно указано, что кеш Oracle Implicit Connection (то есть тот, который использует OracleDataSource) устарел:

Драйверы Oracle JDBC, выпуск 11.2.0.1.0, производство Readme.txt

Что нового в этой версии?

Универсальный пул подключений В этом выпуске функция Oracle Implicit Connection Cache осуждается. Пользователям настоятельно рекомендуется использовать новый универсальный Пул подключений вместо. UCP имеет все функции ICC, а также многое другое. 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>

Ключ должен указать правильный фабричный класс и правильный фабричный метод

9 голосов
/ 16 сентября 2009

PDS является «универсальным», поскольку обеспечивает тот же уровень функциональности пула, который вы получаете в ODS для баз данных не-Oracle, например, MySQL.

См. Руководство по разработке UCP , статью на веб-сайте Oracle и Руководство по переходу UCP

Я не вижу непосредственной выгоды от перехода на UCP (PDS) с ODS, но, возможно, в будущем Oracle откажется от некоторых функций ODS. Некоторое время я использовал ODS, и на данный момент я вполне доволен этим, но если бы я начал все сначала, я бы пошел с PDS.

4 голосов
/ 15 декабря 2010

Я провел обширную оценку UCP и решил НЕ использовать UCP - , пожалуйста, просмотрите этот пост для получения подробной информации.

3 голосов
/ 14 октября 2011

Я тоже тестирую UCP и обнаруживаю, что у меня проблемы с производительностью в приложении на основе пула потоков. Сначала я пробовал OracleDataSource, но у меня возникли проблемы с его настройкой для пакетной обработки. Я продолжаю получать исключения NullPointerException в соединениях, что наводит меня на мысль, что у меня какая-то утечка соединений, но только с некоторыми приложениями, которыми мы управляем, которые не ориентированы на пакетные процессы, и OracleDataSource работает хорошо.

Основываясь на этом посте и нескольких других исследованиях, которые я нашел, я попробовал UCP. Я обнаружил, что при достаточной настройке я могу избавиться от закрытых соединений / исключений NullPointerException при ошибках стиля соединений, но сборщик мусора терпит поражение. Долгосрочный сборщик мусора быстро заполняется и, кажется, никогда не освобождается до тех пор, пока приложение не завершит работу. Иногда это может занять несколько дней, если нагрузка действительно большая. Я также заметил, что обработка данных занимает больше времени. Я сравниваю это с устаревшим классом OracleCacheImpl (который мы сейчас используем в производстве, потому что он все еще «просто работает»), где он использует треть памяти GC, которую UCP делает и обрабатывает файлы гораздо быстрее. Во всех других приложениях UCP, кажется, работает нормально и справляется практически со всем, что я к нему добавляю, но приложение Thread Pool является основным приложением, и я не могу рисковать GC Exception в работе.

3 голосов
/ 13 января 2011

Я протестировал UCP и развернул его в рабочей среде в приложении Spring 3.0.5 Hibernate, используя контейнеры прослушивания Spring JMS и сеансы и транзакции, управляемые Spring, с помощью аннотации @Transactional. Иногда данные вызывают ошибки ограничения SQL из-за того, что отдельные потоки слушателей пытаются обновить одну и ту же запись. Когда это происходит, исключение выдается одним методом, аннотированным @Transactional, и ошибка регистрируется в базе данных, используя другой метод, аннотированный @Transactional. По какой-то причине этот процесс, по-видимому, приводит к утечке курсора, которая в конечном итоге складывается и вызывает ошибку превышения предела открытого курсора ORA-01000, в результате чего поток прекращает обработку чего-либо.

OracleDataSource, работающий в том же коде, похоже, не пропускает курсоры, поэтому не вызывает этой проблемы.

Это довольно странный сценарий, но он показывает мне, что пока слишком рано использовать UCP в приложении с такой структурой.

2 голосов
/ 16 декабря 2014

Неявное кэширование соединения работает немного лучше, чем UCP, если вы используете проверку соединения. Это соответствует ошибке 16723836, которую планируется исправить в 12.1.0.2.

Пул UCP становится все дороже получать / возвращать соединения по мере увеличения параллельной нагрузки. Тест сравнивает оракула неявное кэширование соединения, пул Tomcat и UCP. Все 3 сконфигурирован так, чтобы разрешить максимум 200 подключений, минимум 20 подключений и начальный размер 2. Все 3 настроены для проверки соединений как они удалены из бассейна. В пуле tomcat используется оператор "select sysdate from dual "для проверки.

Эти результаты получены на 64-битном узле RedHat с 64 логическими ядрами (32 физических) и 128 ГБ оперативной памяти.

При 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
0 голосов
/ 11 ноября 2014

Существует два возможных способа использования UCP в Spring Bean.xml.

Для 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

0 голосов
/ 26 июля 2012

Я пробовал 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;
      }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...