<?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 => 'es',
  ),
  'this' => 
  array (
    0 => 'oci8.taf.php',
    1 => 'El soporte de la reanudaci&oacute;n transparente de aplicaci&oacute;n (TAF) de OCI8',
    2 => 'El soporte de la reanudaci&oacute;n transparente de aplicaci&oacute;n (TAF) de OCI8',
  ),
  'up' => 
  array (
    0 => 'book.oci8.php',
    1 => 'OCI8',
  ),
  'prev' => 
  array (
    0 => 'oci8.fan.php',
    1 => 'Soporte de FAN (Fast Application Notification : Notificaci&oacute;n R&aacute;pida de Aplicaci&oacute;n) OCI8',
  ),
  'next' => 
  array (
    0 => 'oci8.dtrace.php',
    1 => 'OCI8 y rastreo din&aacute;mico de DTrace',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'es',
    'path' => 'reference/oci8/taf.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="oci8.taf" class="chapter">
 <h1 class="title">El soporte de la reanudación transparente de aplicación (TAF) de OCI8</h1>

 <p class="para">
  TAF es una funcionalidad de la base de datos Oracle que proporciona alta disponibilidad.
  Permite que las aplicaciones PHP OCI8 se reconecten automáticamente a
  una base de datos preconfigurada cuando la conectividad a la base de datos falla debido
  a una falla de instancia o de red.
 </p>
 <p class="para">
  En un sistema de base de datos Oracle configurado, TAF ocurre cuando la aplicación PHP
  detecta que la instancia de la base de datos está fuera de servicio o inalcanzable. Establece una conexión
  a otro nodo en una configuración Oracle <a href="https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-DEF850F6-27E9-428E-B8FC-530230D78AD2" class="link external">&raquo;&nbsp;RAC</a>,
  una base de datos de respaldo en caliente, o la misma instancia de la base de datos
  ella misma. Consulte el <a href="https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-F7817CD2-4A2C-4D37-BD36-56DBABD4725F" class="link external">&raquo;&nbsp;Guía del programador de la interfaz de llamada Oracle</a>
  para más información sobre OCI TAF.
 </p>
 <p class="para">
  Una función de retrollamada de aplicación puede ser registrada
  con <span class="function"><a href="function.oci-register-taf-callback.php" class="function">oci_register_taf_callback()</a></span>. Durante
  la reanudación, el procesamiento normal de la aplicación se detiene y la retrollamada registrada es invocada.
  La función de retrollamada notifica a la aplicación de los eventos de reanudación. Si la reanudación tiene éxito,
  el procesamiento normal se reanudará. Si la reanudación es abandonada, todas las operaciones de base de datos
  siguientes en la aplicación fallarán debido a la falta de una conexión disponible.
 </p>
 <p class="para">
  Cuando la conexión falla en otra base de datos, la función de retrollamada puede
  restablecer cualquier estado de conexión necesario, por ejemplo, rejugando
  los comandos ALTER SESSION necesarios si el servicio de base de datos no tenía
  -failover_restore activado.
 </p>
 <p class="para">
  Una función de retrollamada de aplicación puede ser eliminada llamando a <span class="function"><a href="function.oci-unregister-taf-callback.php" class="function">oci_unregister_taf_callback()</a></span>.
 </p>

 <div class="section">
  <h2 class="title">Configuración de la reanudación transparente de aplicación</h2>
  <p class="para">
   TAF puede ser configurado del lado PHP OCI8 o en la configuración de la
   base de datos. Si ambos están configurados, los parámetros del lado de la base de datos
   tienen prioridad.
  </p>
  <p class="para">
   Configurar TAF en PHP OCI8 (el lado cliente) incluyendo el
   parámetro FAILOVER_MODE en la parte CONNECT_DATA de un
   descriptor de conexión. Consulte la sección
   Configuración de la reanudación transparente de aplicación
   del <a href="https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-8F532535-C401-4B51-BE0B-04FD74BB0621" class="link external">&raquo;&nbsp;
   Guía del administrador de Oracle Database Net Services</a>
   para más información sobre la configuración del lado cliente de TAF.
  </p>
  <p class="para">
   Un ejemplo de tnsnames.ora para configurar TAF reconectando a
   la misma instancia de la base de datos:
  </p>
  <p class="para">
    <div class="informalexample">
     <div class="example-contents screen">
<div class="cdata"><pre>
    ORCL =
      (DESCRIPTION =
        (ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521))
        (CONNECT_DATA =
          (SERVICE_NAME = orclpdb1)
          (FAILOVER_MODE =
            (TYPE = SELECT)
            (METHOD = BASIC)
            (RETRIES = 20)
            (DELAY = 15))))
 </pre></div>
     </div>
   </div>
  </p>
  <p class="para">
   También es posible configurar TAF del lado de la base de datos
   modificando el servicio objetivo con
   <a href="https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-8DC4D5E0-CA9D-47BC-BAD0-8769405AFEC5" class="link external">&raquo;&nbsp;srvctl</a>
   (para RAC) o la procedimiento empaquetado
   <a href="https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-C11449DC-EEDE-4BB8-9D2C-0A45198C1928" class="link external">&raquo;&nbsp;
   DBMS_SERVICE.MODIFY_SERVICE</a>
   (para bases de datos de instancia única).
  </p>
 </div>
 <div class="section">
  <h2 class="title">Uso de las funciones de retrollamada TAF en OCI8</h2>
  <p class="para">
   Una función de retrollamada TAF es una función de aplicación que puede ser
   registrada para ser llamada durante la reanudación. Es llamada
   varias veces durante la reanudación de la conexión de la aplicación.
  </p>
  <p class="para">
   La función de retrollamada es llamada por primera vez cuando se detecta una pérdida de conexión.
   Esto permite que la aplicación actúe en consecuencia para
   los retrasos venideros de la reanudación. Si la reanudación tiene éxito,
   la función de retrollamada es invocada después de que la conexión sea restablecida
   y utilizable. En ese momento, la aplicación puede resincronizar
   los parámetros de sesión y tomar acciones tales como
   informar al usuario que una reanudación ha ocurrido. Si la reanudación
   es infructuosa, una retrollamada ocurre para informar a la aplicación
   que una reanudación no ha ocurrido y que la conexión no es utilizable.
  </p>
  <p class="para">
   La interfaz de una función de retrollamada TAF definida por el usuario es la siguiente:
  </p>
  <div class="methodsynopsis dc-description">
   <span class="methodname"><strong>userCallbackFn</strong></span>(<span class="methodparam"><span class="type"><a href="language.types.resource.php" class="type resource">resource</a></span> <code class="parameter">$connection</code></span>, <span class="methodparam"><span class="type"><a href="language.types.integer.php" class="type int">int</a></span> <code class="parameter">$event</code></span>, <span class="methodparam"><span class="type"><a href="language.types.integer.php" class="type int">int</a></span> <code class="parameter">$type</code></span>): <span class="type"><a href="language.types.integer.php" class="type int">int</a></span></div>

  <p class="para">
   <dl>
    
     <dt><code class="parameter">connection</code></dt>
     <dd>
      <p class="para">
       La conexión Oracle en la que la retrollamada TAF ha sido
       registrada vía <span class="function"><a href="function.oci-register-taf-callback.php" class="function">oci_register_taf_callback()</a></span>.
       La conexión no es válida hasta que la
       reanudación no termine con éxito.
      </p>
     </dd>
    
    
     <dt><code class="parameter">event</code></dt>
     <dd>
      <p class="para">
       El evento de reanudación indica el estado actual de
       la reanudación.
      </p>
      <p class="para">
       <ul class="itemizedlist">
        <li class="listitem">
         <p class="para">
          <strong><code><a href="oci8.constants.php#constant.oci-fo-begin">OCI_FO_BEGIN</a></code></strong> indica que
          la reanudación ha detectado una pérdida de conexión y que
          la reanudación comienza.
         </p>
        </li>
        <li class="listitem">
         <p class="para">
          <strong><code><a href="oci8.constants.php#constant.oci-fo-end">OCI_FO_END</a></code></strong> indica que la
          reanudación ha tenido éxito.
         </p>
        </li>
        <li class="listitem">
         <p class="para">
          <strong><code><a href="oci8.constants.php#constant.oci-fo-abort">OCI_FO_ABORT</a></code></strong> indica que
          la reanudación ha fallado y que no hay opción
          de reintentar.
         </p>
        </li>
        <li class="listitem">
         <p class="para">
          <strong><code><a href="oci8.constants.php#constant.oci-fo-error">OCI_FO_ERROR</a></code></strong> indica asimismo
          que la reanudación ha fallado, pero da a
          la aplicación la oportunidad de manejar el error
          y devolver OCI_FO_RETRY para reintentar la reanudación.
         </p>
        </li>
        <li class="listitem">
         <p class="para">
           <strong><code><a href="oci8.constants.php#constant.oci-fo-reauth">OCI_FO_REAUTH</a></code></strong> indica que
           un usuario Oracle ha sido reautenticado.
         </p>
        </li>
       </ul>
      </p>
     </dd>
    
    
     <dt><code class="parameter">type</code></dt>
     <dd>
      <p class="para">
       El tipo de reanudación. Esto permite a la retrollamada saber
       qué tipo de reanudación la aplicación ha solicitado. Los
       valores habituales son los siguientes:
      </p>
      <p class="para">
       <ul class="itemizedlist">
        <li class="listitem">
         <p class="para">
          <strong><code><a href="oci8.constants.php#constant.oci-fo-session">OCI_FO_SESSION</a></code></strong> indica que
          el usuario ha solicitado únicamente la reanudación de sesión.
          Por ejemplo, si la conexión de un usuario se pierde,
          una nueva sesión es automáticamente creada para
          el usuario en la base de datos de respaldo. Este tipo de reanudación
          no intenta recuperar los SELECT.
         </p>
        </li>
        <li class="listitem">
         <p class="para">
          <strong><code><a href="oci8.constants.php#constant.oci-fo-select">OCI_FO_SELECT</a></code></strong> indica que
          el usuario ha solicitado la reanudación SELECT asimismo.
          Permite a los usuarios con cursores abiertos
          continuar recuperándolos después de una falla.
         </p>
        </li>
       </ul>
      </p>
     </dd>
    
    
     <dt><code class="parameter">return value</code></dt>
     <dd>
      <p class="para">
       <ul class="itemizedlist">
        <li class="listitem">
         <p class="para">
          <code class="literal">0</code> indica que los pasos de reanudación
          deben continuar normalmente.
         </p>
        </li>
        <li class="listitem">
         <p class="para">
          <strong><code><a href="oci8.constants.php#constant.oci-fo-retry">OCI_FO_RETRY</a></code></strong> indica que
          la reanudación debe ser intentada nuevamente por Oracle.
          En caso de error al reanudar a una nueva
          conexión, TAF es capaz de reintentar la reanudación.
          En general, el código de la aplicación debe dormir
          durante un cierto tiempo antes de devolver OCI_FO_RETRY.
         </p>
        </li>
       </ul>
      </p>
     </dd>
    
   </dl>
  </p>
  <div class="example" id="example-1">
   <p><strong>Ejemplo #1 Registro de una función de retrollamada TAF</strong></p>
   <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #FF8000">// Definición de la función de retrollamada del espacio de usuario<br /></span><span style="color: #007700">class </span><span style="color: #0000BB">MyClass </span><span style="color: #007700">{<br />    public static </span><span style="color: #0000BB">$retry_count</span><span style="color: #007700">;<br />    public static function </span><span style="color: #0000BB">TAFCallback</span><span style="color: #007700">(</span><span style="color: #0000BB">$conn</span><span style="color: #007700">, </span><span style="color: #0000BB">$event</span><span style="color: #007700">, </span><span style="color: #0000BB">$type</span><span style="color: #007700">)<br />    {<br />        switch (</span><span style="color: #0000BB">$event</span><span style="color: #007700">) {<br />            case </span><span style="color: #0000BB">OCI_FO_BEGIN</span><span style="color: #007700">:<br />                </span><span style="color: #0000BB">printf</span><span style="color: #007700">(</span><span style="color: #DD0000">" Reanudando ... Por favor, espere\n"</span><span style="color: #007700">);<br />                </span><span style="color: #0000BB">printf</span><span style="color: #007700">(</span><span style="color: #DD0000">" El tipo de reanudación se encontró que era %s \n"</span><span style="color: #007700">,<br />                       ((</span><span style="color: #0000BB">$type</span><span style="color: #007700">==</span><span style="color: #0000BB">OCI_FO_SESSION</span><span style="color: #007700">) ? </span><span style="color: #DD0000">"SESSION"<br />                        </span><span style="color: #007700">:((</span><span style="color: #0000BB">$type</span><span style="color: #007700">==</span><span style="color: #0000BB">OCI_FO_SELECT</span><span style="color: #007700">) ? </span><span style="color: #DD0000">"SELECT" </span><span style="color: #007700">: </span><span style="color: #DD0000">"UNKNOWN!"</span><span style="color: #007700">)));<br />                </span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">$retry_count </span><span style="color: #007700">= </span><span style="color: #0000BB">0</span><span style="color: #007700">;<br />                break;<br />            case </span><span style="color: #0000BB">OCI_FO_ABORT</span><span style="color: #007700">:<br />                </span><span style="color: #FF8000">// La aplicación no puede continuar utilizando la base de datos<br />                </span><span style="color: #0000BB">printf</span><span style="color: #007700">(</span><span style="color: #DD0000">" Reanudación abortada. La reanudación no tendrá lugar.\n"</span><span style="color: #007700">);<br />                break;<br />            case </span><span style="color: #0000BB">OCI_FO_END</span><span style="color: #007700">:<br />                </span><span style="color: #FF8000">// Reanudación exitosa. Informar a los usuarios que una reanudación ha ocurrido.<br />                </span><span style="color: #0000BB">printf</span><span style="color: #007700">(</span><span style="color: #DD0000">" Reanudación terminada ... reanudando servicios\n"</span><span style="color: #007700">);<br />                break;<br />            case </span><span style="color: #0000BB">OCI_FO_REAUTH</span><span style="color: #007700">:<br />                </span><span style="color: #0000BB">printf</span><span style="color: #007700">(</span><span style="color: #DD0000">" Usuario reanudado ... reanudando servicios\n"</span><span style="color: #007700">);<br />                </span><span style="color: #FF8000">// Rejugar todas las comandos ALTER SESSION asociadas a esta conexión<br />                // por ejemplo oci_parse($conn, 'ALTER SESSION ...');<br />                </span><span style="color: #007700">break;<br />            case </span><span style="color: #0000BB">OCI_FO_ERROR</span><span style="color: #007700">:<br />                </span><span style="color: #FF8000">// Detener los intentos si ya se ha intentado 20 veces.<br />                </span><span style="color: #007700">if (</span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">$retry_count </span><span style="color: #007700">&gt;= </span><span style="color: #0000BB">20</span><span style="color: #007700">)<br />                    return </span><span style="color: #0000BB">0</span><span style="color: #007700">;<br />                </span><span style="color: #0000BB">printf</span><span style="color: #007700">(</span><span style="color: #DD0000">" Error de reanudación recibido. Durmiendo...\n"</span><span style="color: #007700">);<br />                </span><span style="color: #0000BB">sleep</span><span style="color: #007700">(</span><span style="color: #0000BB">10</span><span style="color: #007700">);<br />                </span><span style="color: #0000BB">self</span><span style="color: #007700">::</span><span style="color: #0000BB">$retry_count</span><span style="color: #007700">++;<br />                return </span><span style="color: #0000BB">OCI_FO_RETRY</span><span style="color: #007700">; </span><span style="color: #FF8000">// reintentar reanudación<br />                </span><span style="color: #007700">break;<br />            default:<br />                </span><span style="color: #0000BB">printf</span><span style="color: #007700">(</span><span style="color: #DD0000">"Evento de reanudación incorrecto: %d.\n"</span><span style="color: #007700">, </span><span style="color: #0000BB">$event</span><span style="color: #007700">);<br />                break;<br />        }<br />        return </span><span style="color: #0000BB">0</span><span style="color: #007700">;<br />    }<br />}<br /><br /></span><span style="color: #0000BB">$fn_name </span><span style="color: #007700">= </span><span style="color: #DD0000">'MyClass::TAFCallback'</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">$conn </span><span style="color: #007700">= </span><span style="color: #0000BB">oci_connect</span><span style="color: #007700">(</span><span style="color: #DD0000">'hr'</span><span style="color: #007700">, </span><span style="color: #DD0000">'welcome'</span><span style="color: #007700">, </span><span style="color: #DD0000">'orcl'</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$sysconn </span><span style="color: #007700">= </span><span style="color: #0000BB">oci_connect</span><span style="color: #007700">(</span><span style="color: #DD0000">'system'</span><span style="color: #007700">, </span><span style="color: #DD0000">'oracle'</span><span style="color: #007700">, </span><span style="color: #DD0000">'orcl'</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">// Usar una conexión privilegiada para construir una instrucción SQL que iniciará la reanudación<br /></span><span style="color: #0000BB">$sql </span><span style="color: #007700">= &lt;&lt;&lt; 'END'<br /></span><span style="color: #DD0000">select unique 'alter system disconnect session '''||sid||','||serial#||''''<br />from v$session_connect_info<br />where sid = sys_context('USERENV', 'SID')<br /></span><span style="color: #007700">END;<br /><br /></span><span style="color: #0000BB">$s </span><span style="color: #007700">= </span><span style="color: #0000BB">oci_parse</span><span style="color: #007700">(</span><span style="color: #0000BB">$conn</span><span style="color: #007700">, </span><span style="color: #0000BB">$sql</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">oci_execute</span><span style="color: #007700">(</span><span style="color: #0000BB">$s</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$r </span><span style="color: #007700">= </span><span style="color: #0000BB">oci_fetch_array</span><span style="color: #007700">(</span><span style="color: #0000BB">$s</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$disconnectssql </span><span style="color: #007700">= </span><span style="color: #0000BB">$r</span><span style="color: #007700">[</span><span style="color: #0000BB">0</span><span style="color: #007700">];<br /><br /></span><span style="color: #0000BB">oci_register_taf_callback</span><span style="color: #007700">(</span><span style="color: #0000BB">$conn</span><span style="color: #007700">, </span><span style="color: #0000BB">$fn_name</span><span style="color: #007700">); </span><span style="color: #FF8000">// Registrar TAFCallback a Oracle TAF<br /><br /></span><span style="color: #007700">print </span><span style="color: #DD0000">"Analizando consulta de usuario\n"</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$sql </span><span style="color: #007700">= </span><span style="color: #DD0000">"select systimestamp from dual"</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$stmt </span><span style="color: #007700">= </span><span style="color: #0000BB">oci_parse</span><span style="color: #007700">(</span><span style="color: #0000BB">$conn</span><span style="color: #007700">, </span><span style="color: #0000BB">$sql</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">// Por ejemplo, si una pérdida de conexión ocurre en este momento, oci_execute() detectará<br />// la pérdida y la reanudación comenzará. Durante la reanudación, oci_execute() invocará<br />// la función de retrollamada TAF varias veces. Si la reanudación tiene éxito,<br />// una nueva conexión es creada de manera transparente y oci_execute() continuará como<br />// de costumbre. Los parámetros de sesión de la conexión pueden ser restablecidos en la función de retrollamada TAF.<br />// Si la reanudación es abandonada, oci_execute() devolverá un error<br />// ya que una conexión válida no está disponible.<br /><br />// Desconectar al usuario, lo que inicia la reanudación<br /></span><span style="color: #007700">print </span><span style="color: #DD0000">"Desconectando al usuario\n"</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$discsql </span><span style="color: #007700">= </span><span style="color: #0000BB">oci_parse</span><span style="color: #007700">(</span><span style="color: #0000BB">$sysconn</span><span style="color: #007700">, </span><span style="color: #0000BB">$disconnectssql</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">oci_execute</span><span style="color: #007700">(</span><span style="color: #0000BB">$discsql</span><span style="color: #007700">);<br /><br />print </span><span style="color: #DD0000">"Ejecutando consulta de usuario\n"</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$e </span><span style="color: #007700">= </span><span style="color: #0000BB">oci_execute</span><span style="color: #007700">(</span><span style="color: #0000BB">$stmt</span><span style="color: #007700">);<br />if (!</span><span style="color: #0000BB">$e</span><span style="color: #007700">) {<br />    </span><span style="color: #0000BB">$m </span><span style="color: #007700">= </span><span style="color: #0000BB">oci_error</span><span style="color: #007700">(</span><span style="color: #0000BB">$stmt</span><span style="color: #007700">);<br />    </span><span style="color: #0000BB">trigger_error</span><span style="color: #007700">(</span><span style="color: #DD0000">"No se pudo ejecutar la sentencia: "</span><span style="color: #007700">. </span><span style="color: #0000BB">$m</span><span style="color: #007700">[</span><span style="color: #DD0000">'message'</span><span style="color: #007700">], </span><span style="color: #0000BB">E_USER_ERROR</span><span style="color: #007700">);<br />}<br /></span><span style="color: #0000BB">$row </span><span style="color: #007700">= </span><span style="color: #0000BB">oci_fetch_array</span><span style="color: #007700">(</span><span style="color: #0000BB">$stmt</span><span style="color: #007700">);<br />print </span><span style="color: #0000BB">$row</span><span style="color: #007700">[</span><span style="color: #0000BB">0</span><span style="color: #007700">] . </span><span style="color: #DD0000">"\n"</span><span style="color: #007700">;<br /><br /></span><span style="color: #FF8000">// hacer otras instrucciones SQL con la nueva conexión, si es válida<br />// $stmt = oci_parse($conn,  . . .);<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

  </div>
 </div>

 <div class="section">
  <h2 class="title">Ver también</h2>
  <ul class="simplelist">
   <li><span class="function"><a href="function.oci-register-taf-callback.php" class="function">oci_register_taf_callback()</a></span></li>
   <li><span class="function"><a href="function.oci-unregister-taf-callback.php" class="function">oci_unregister_taf_callback()</a></span></li>
  </ul>
 </div>

</div>
<?php manual_footer($setup); ?>