<?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 => 'ja',
  ),
  'this' => 
  array (
    0 => 'oci8.connection.php',
    1 => 'OCI8 接続のハンドリングおよびプーリング',
    2 => 'OCI8 接続のハンドリングおよびプーリング',
  ),
  'up' => 
  array (
    0 => 'book.oci8.php',
    1 => 'OCI8',
  ),
  'prev' => 
  array (
    0 => 'oci8.examples.php',
    1 => '例',
  ),
  'next' => 
  array (
    0 => 'oci8.fan.php',
    1 => 'OCI8 高速アプリケーション通知 (FAN) サポート',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'ja',
    '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 接続のハンドリングおよびプーリング</h1>

 <div class="section">
  <h2 class="title">接続関数</h2>
  <p class="para">
   oci8 拡張モジュールは Oracle に接続するための 3
   つの異なる関数を提供しています。標準の接続関数は
   <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">
   もしアプリケーションが信用された異なる Web ユーザー毎に
   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> を複数回コールする場合、
   2 番目以降は既存の接続ハンドルを返します。<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> も同様の動作をしますが、
   キャッシュは独立して維持され、リクエスト間で残存します。
  </p>
  <p class="para">
   このキャッシュ機能は忘れてはならないほど重要です。
   それは、2 つのハンドルがトランザクション的に独立していない
   (実際には同じ接続なので、どのような種類の独立もありません)
   ためです。もしアプリケーションが 2
   つの別々でトランザクション的に独立した接続を必要とする場合、
   <span class="function"><a href="function.oci-new-connect.php" class="function">oci_new_connect()</a></span> を使用すべきです。
  </p>
  <p class="para">
   PHP プロセス終了時に <span class="function"><a href="function.oci-pconnect.php" class="function">oci_pconnect()</a></span> キャッシュは消去され、
   データベース接続は全て閉じられます。
   そのため、持続的接続を効果的に使用するには、
   PHP は Apache のモジュールであるか、または FPM によって使用されるか、
   または同様のものでなければいけません。
   PHP が CGI によって、またはコマンドラインを介して使用される場合、
   持続的接続には <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-new-connect.php" class="function">oci_new_connect()</a></span> は、他の既存の接続が存在したとしても
   常に Oracle サーバーへの新規接続を生成します。
   特にアプリケーションの最も負荷が高い部分など、
   高トラフィックな Web アプリケーションに対しては
   <span class="function"><a href="function.oci-new-connect.php" class="function">oci_new_connect()</a></span> の使用を避けてください。
  </p>
  <p class="para">
   持続的接続をユーザーが閉じることができます。
   これにより、接続リソースの使い方をユーザーがより強く制御できます。
   持続的接続は、PHP の変数が参照していない場合にも、
   自動的に閉じられるようになっています。
   たとえば、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 のプロセスが再度 fork した後、
   PHP の持続的接続は再接続されます。
   これは、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 は、ごく少数のデータベーススキーマを使用し、データベース接続を短時間オープン状態に
   保つアプリケーションに適しています。
   その他のアプリケーションは、 Oracle のデフォルトの <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">
   OCI8 で DRCP を利用可能にするには、 PHP で使用する Oracle クライアントライブラリ、
   及び Oracle データベースのバージョンが共に 11g 以降でなければいけません。
  </p>
  <p class="para">
   DRCP についてのドキュメントはいくつかの Oracle マニュアルに見つかります。
   例えば、使用法の情報のために、 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>
   をご覧ください。
   <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">
      DRCP の設定を構成するために、
      任意で <code class="literal">dbms_connection_pool.alter_param()</code> を使用します。
      現行のプール設定は、 <code class="literal">DBA_CPOOL_INFO</code> ビューで照会できます。
     </p>
    </li>
    <li class="listitem">
     <p class="para">
      使用する接続文字列を更新します。
      <code class="literal">MYDB</code> のようなネットワーク接続名を使って現在接続する PHP アプリケーションでは、
     </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 で Easy Connect 構文を修正して、サービス名の後に
      <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 を使うアプリケーションでは、
    Oracle <code class="literal">Shared</code> サーバー(マルチスレッドサーバーとして既知)を使用することにより、
    必要なデータベース・メモリー量を減らせます。
    詳細は 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> というエラーで失敗します。
   これは Oracle データベース 11g の制約に典拠が示されています。
   </p>
  </p></blockquote>
 </div>
</div>
<?php manual_footer($setup); ?>