<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc';
$TOC = array();
$TOC_DEPRECATED = array();
$PARENTS = array();
include_once dirname(__FILE__) ."/toc/book.oci8.inc";
$setup = array (
  'home' => 
  array (
    0 => 'index.php',
    1 => 'PHP Manual',
  ),
  'head' => 
  array (
    0 => 'UTF-8',
    1 => 'ru',
  ),
  'this' => 
  array (
    0 => 'oci8.connection.php',
    1 => 'Работа с соединениями OCI8 и Connection Pooling',
    2 => 'Работа с соединениями OCI8 и Connection Pooling',
  ),
  'up' => 
  array (
    0 => 'book.oci8.php',
    1 => 'OCI8',
  ),
  'prev' => 
  array (
    0 => 'oci8.examples.php',
    1 => 'Примеры',
  ),
  'next' => 
  array (
    0 => 'oci8.fan.php',
    1 => 'Поддержка OCI8 Fast Application Notification (FAN)',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'ru',
    'path' => 'reference/oci8/connection.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="oci8.connection" class="chapter">
 <h1 class="title">Работа с соединениями OCI8 и Connection Pooling</h1>

 <div class="section">
  <h2 class="title">Функции подключения</h2>
  <p class="para">
   Модуль OCI8 предоставляет три различных функции для подключения
   к серверу Oracle. Стандартная функция соединения —
   <span class="function"><a href="function.oci-connect.php" class="function">oci_connect()</a></span>. Она создаёт соединение к базе данных
   Oracle и возвращает ресурс, который используется при последующих обращениях
   к БД.
  </p>
  <p class="para">
   Подключение к серверу Oracle является достаточно дорогостоящей операцией
   с точки зрения времени, которое требуется для выполнения.
   Функция <span class="function"><a href="function.oci-pconnect.php" class="function">oci_pconnect()</a></span> использует постоянный
   кеш соединений, которые могут быть повторно использованы различными
   запросами скриптов. Это означает, что затраты на установку соединения,
   как правило, происходят только единожды на один процесс PHP
   (или на потомка Apache).
  </p>
  <p class="para">
   Если приложение соединяется к серверу Oracle, используя особый набор
   данных для каждого веб-пользователя, то постоянный кеш соединений,
   используемый функцией <span class="function"><a href="function.oci-pconnect.php" class="function">oci_pconnect()</a></span> будет менее
   полезным, поскольку количество одновременных пользователей вырастает до
   того уровня, где он может начать оказывать негативное влияние на
   общую производительность сервера Oracle из-за поддержания слишком
   большого количества простаивающих соединений. Если приложение
   настроено таким образом, то рекомендуется либо настроить его с
   помощью параметров конфигурации
   <a href="oci8.configuration.php#ini.oci8.max-persistent" class="link">oci8.max_persistent</a>
   и <a href="oci8.configuration.php#ini.oci8.persistent-timeout" class="link">oci8.persistent_timeout</a>
   (это даст возможность управления размером кеша постоянных соединений и
   их время жизни), либо использовать Oracle Database
   Resident Connection Pooling (в Oracle Database 11g и новее), либо использовать функцию
   <span class="function"><a href="function.oci-connect.php" class="function">oci_connect()</a></span> вместо неё.
  </p>
  <p class="para">
   Вместе <span class="function"><a href="function.oci-connect.php" class="function">oci_connect()</a></span>
   и <span class="function"><a href="function.oci-pconnect.php" class="function">oci_pconnect()</a></span> используют кеш подключений; если
   множество вызовов <span class="function"><a href="function.oci-connect.php" class="function">oci_connect()</a></span> использует одинаковые
   параметры в данном скрипте, второй и последующие вызовы вернут
   существующий дескриптор соединения. Кеш, который использует функция
   <span class="function"><a href="function.oci-connect.php" class="function">oci_connect()</a></span>, очищается по завершению выполнения
   скрипта, или когда соединение неявно закрывается. У функции
   <span class="function"><a href="function.oci-pconnect.php" class="function">oci_pconnect()</a></span> похожее поведение, хотя её кеш
   обрабатывается отдельно и остаётся действующим между
   HTTP-запросами.
  </p>
  <p class="para">
   Эта возможность кеширования означает, что два дескриптора не изолированы
   транзакционно (они на самом деле являются одним и тем же дескриптором, поэтому здесь
   нет никакой изоляции). Если приложению необходимы два отдельных
   транзакционно изолированных соединения, то необходимо использовать
   функцию <span class="function"><a href="function.oci-new-connect.php" class="function">oci_new_connect()</a></span>.
  </p>
  <p class="para">
   Кеш функции <span class="function"><a href="function.oci-pconnect.php" class="function">oci_pconnect()</a></span> очищается и закрываются
   все соединения к БД, когда завершается процесс PHP. Поэтому
   эффективное использование постоянных соединений требует, чтобы PHP был
   модулем Apache или использовался с FPM или подобным. Постоянные соединения
   не будут иметь никаких преимуществ перед <span class="function"><a href="function.oci-connect.php" class="function">oci_connect()</a></span>,
   когда PHP используется с CGI или через командную строку.
  </p>
  <p class="para">
   Функция <span class="function"><a href="function.oci-new-connect.php" class="function">oci_new_connect()</a></span> каждый раз создаёт
   новое соединение с сервером Oracle, несмотря на то, что другие
   соединения могут уже существовать. Высоконагруженным веб-приложениям
   следует избегать использования <span class="function"><a href="function.oci-new-connect.php" class="function">oci_new_connect()</a></span>, особенно
   в самых загруженных частях приложения.
  </p>
  <p class="para">
   Постоянные соединения могут быть закрыты пользователем, что
   даёт более полный контроль над использованием ресурсов. Также постоянные соединения могут
   быть закрыты автоматически, если не осталось переменных PHP указывающих на них,
   например при завершении выполнения пользовательской функции. Закрытие соединения
   откатит все не подтверждённые транзакции. Эти изменения в постоянных подключениях
   делают их поведение аналогичным не постоянным соединениям. Чтобы включить старое
   поведение, задайте опцию <a href="oci8.configuration.php#ini.oci8.old-oci-close-semantics" class="link">oci8.old_oci_close_semantics</a> значением
   <em>On</em>.
  </p>
  <p class="para">
   Автоматическое пересоздание постоянных соединений после перезапуска процессов
   Apache или FPM, означает, что Oracle Database <code class="literal">LOGON</code>
   рекомендуется только для настройки атрибутов сеанса, а не для запросов
   на подключение пользователей для отдельных приложений.
  </p>
 </div>
 <div class="section">
  <h2 class="title">Создание пула соединений DRCP</h2>
  <p class="para">
   PHP поддерживает постоянный пул соединений Oracle 11g
   (DRCP). DRCP позволяет более эффективно использовать память СУБД и предоставляет
   высокую масштабируемость. Изменять код приложения для использования DRCP либо
   нет необходимости, либо требуются минимальные изменения.
  </p>
  <p class="para">
   DRCP подходит для приложений, которые подключаются используя несколько
   схем БД и сохраняют соединения к БД открытыми короткий промежуток времени.
   Другим приложениям следует использовать доступные по умолчанию
   <code class="literal">Dedicated</code> серверные процессы или
   использовать <code class="literal">Shared</code> сервера.
  </p>
  <p class="para">
   DRCP приносит пользу всем трём функциям подключения, однако предоставляет
   самую высокую масштабируемость, когда соединения создаются с
   помощью функции <span class="function"><a href="function.oci-pconnect.php" class="function">oci_pconnect()</a></span>.
  </p>
  <p class="para">
   Чтобы функциональность DRCP была доступна в OCI8, клиентские библиотеки Oracle, используемые в
   PHP, и версия сервера баз данных должны быть 11g и новее.
  </p>
  <p class="para">
   Документация по DRCP находится в нескольких руководствах Oracle. К примеру,
   смотрите <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/jjdbc/database-resident-connection-pooling.html" class="link external">&raquo;&nbsp;Конфигурирование
   пула постоянных соединений базы данных</a> в документации Oracle
   для информации по использованию.
   Документ <a href="https://www.oracle.com/technetwork/topics/php/whatsnew/php-scalability-ha-twp-128842.pdf" class="link external">&raquo;&nbsp;техническое
   описание DRCP</a> содержит дополнительную информацию по DRCP.
  </p>
  <p class="para">
   Для использования DRCP, установите модуль OCI8
   и библиотеки Oracle 11g (или новее) и затем выполните следующие действия:
  </p>
  <p class="para">
   <ul class="itemizedlist">
    <li class="listitem">
     <p class="para">
      Как привилегированный администратор БД воспользуйтесь программой
      наподобие SQL*Plus, чтобы запустить пул соединений в СУБД:
     </p>
     <p class="para">
      <div class="informalexample">
       <div class="example-contents screen">
<div class="cdata"><pre>
    SQL&gt; execute dbms_connection_pool.start_pool;
</pre></div>
       </div>
      </div>
     </p>
    </li>
    <li class="listitem">
     <p class="para">
      Дополнительно можно использовать
      <code class="literal">dbms_connection_pool.alter_param()</code>,
      чтобы конфигурировать параметры DRPC. Текущие настройки пула могут быть
      получены из представления <code class="literal">DBA_CPOOL_INFO</code>.
     </p>
    </li>
    <li class="listitem">
     <p class="para">
      Обновите используемую строку соединения. К примеру, для приложений PHP, которые
      сейчас соединяются, используя Network Connect Name
      <code class="literal">MYDB</code>:
     </p>
     <p class="para">
      <div class="informalexample">
       <div class="example-contents screen">
<div class="cdata"><pre>
    $c = oci_pconnect(&quot;myuser&quot;, &quot;mypassword&quot;, &quot;MYDB&quot;);
</pre></div>
       </div>
      </div>
     </p>
     <p class="para">
      измените файл tnsnames.ora и добавьте
      оператор <code class="literal">(SERVER=POOLED)</code>, например:
     </p>
     <p class="para">
      <div class="informalexample">
       <div class="example-contents screen">
<div class="cdata"><pre>
    MYDB = (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp) (HOST=myhost.dom.com)
           (PORT=1521))(CONNECT_DATA=(SERVICE_NAME=sales)
           (SERVER=POOLED)))
</pre></div>
       </div>
      </div>
     </p>
     <p class="para">
      В качестве альтернативы можно изменить синтаксис упрощённого соединения
      в PHP и добавить туда <code class="literal">:POOLED</code> после имени сервиса:
     </p>
     <p class="para">
      <div class="informalexample">
       <div class="example-contents screen">
<div class="cdata"><pre>
    $c = oci_pconnect(&quot;myuser&quot;, &quot;mypassword&quot;, &quot;myhost.dom.com:1521/sales:POOLED&quot;);
</pre></div>
       </div>
      </div>
     </p>
    </li>
    <li class="listitem">
     <p class="para">
      Отредактируйте <var class="filename">php.ini</var> и выберите имя класса соединения. Это имя
      устанавливает логическое разделение пула соединений и может использоваться,
      чтобы изолировать пул для отдельных приложений. Любое PHP-приложение
      с одинаковым именем пользователя и классом для соединения
      будет иметь возможность совместно использовать соединения в пуле, получая
      бОльшую масштабируемость.
     </p>
     <p class="para">
      <div class="informalexample">
       <div class="example-contents screen">
<div class="cdata"><pre>
    oci8.connection_class = &quot;MY_APPLICATION_NAME&quot;
</pre></div>
       </div>
      </div>
     </p>
    </li>
    <li class="listitem">
     <p class="para">
      Запустите приложение, соединяющееся с базой 11g и новее.
     </p>
    </li>
   </ul>
  </p>
  <blockquote class="note"><p><strong class="note">Замечание</strong>: 
   <p class="para">
    Приложения, использующие Oracle 10g, которые требуют производительности
    от постоянных соединений, могут уменьшить количество памяти сервера БД,
    которое используется <code class="literal">Shared</code>-серверами Oracle
    (ранее известные как многопоточные сервера). Обратитесь к документации
    Oracle для более подробной информации.
   </p>
  </p></blockquote>
  <blockquote class="note"><p><strong class="note">Замечание</strong>: 
   <p class="para">
    При изменении пароля через DRCP-соединение будет выдаваться
    ошибка <em>ORA-56609: Usage not supported with DRCP</em>.
    Это документированное ограничение of Oracle Database 11g.
   </p>
  </p></blockquote>
 </div>
</div>
<?php manual_footer($setup); ?>