<?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 => 'pt_BR',
  ),
  'this' => 
  array (
    0 => 'oci8.taf.php',
    1 => 'Suporte ao OCI8 Transparent Application Failover (TAF)',
    2 => 'Suporte ao OCI8 Transparent Application Failover (TAF)',
  ),
  'up' => 
  array (
    0 => 'book.oci8.php',
    1 => 'OCI8',
  ),
  'prev' => 
  array (
    0 => 'oci8.fan.php',
    1 => 'Suporte &agrave; Notifica&ccedil;&atilde;o R&aacute;pida de Aplica&ccedil;&atilde;o (FAN) do OCI8',
  ),
  'next' => 
  array (
    0 => 'oci8.dtrace.php',
    1 => 'OCI8 e Rastreamento din&acirc;mico DTrace',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'pt_BR',
    '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">Suporte ao OCI8 Transparent Application Failover (TAF)</h1>

 <p class="para">
  TAF é um recurso do Oracle Database que fornece alta disponibilidade.
  Ele permite que apliações PHP OCI8 se reconectem automaticamente a um
  banco de dados pré-configurado quando a conectividade do banco de dados falha devido a
  uma falha na instância ou na rede.
 </p>
 <p class="para">
  Em um sistema Oracle Database configurado, o TAF ocorre quando a aplicação
  PHP detecta que a instância do banco de dados está inativa
  ou inacessível. Ele estabelece uma conexão com outro nó em uma
  configuração 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>,
  em um banco de dados hot standby ou na própria instância
  de banco
  de dados. Consulte o <a href="https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-F7817CD2-4A2C-4D37-BD36-56DBABD4725F" class="link external">&raquo;&nbsp;Guia
  do programador da Interface de Chamada Oracle</a> para obter mais informações sobre
  o OCI TAF.
 </p>
 <p class="para">
  Um retorno de chamada de aplicação pode ser registrado
  com <span class="function"><a href="function.oci-register-taf-callback.php" class="function">oci_register_taf_callback()</a></span>. Durante a recuperação
  da falha, o processamento normal da aplicação é interrompido e o retorno de chamada
  registrado é invocado. O retorno de chamada notifica a aplicação sobre os
  eventos de falha. Se a recuperação for bem-sucedida, o processamento normal
  será retomado. Se a recuperação abortar, quaisquer operações de banco de dados seguintes
  na aplicação falharão devido à falta de conexão
  disponível.
 </p>
 <p class="para">
  Quando uma conexão se recupera para um outro banco de dados, o retorno de chamada pode
  redefinir qualquer estado de conexão necessário, por exemplo, reproduzindo quaisquer
  comandos ALTER SESSION necessários se o serviço de banco de dados não tiver
  -failover_restore ativado.
 </p>
 <p class="para">
  Um retorno de chamada de aplicação pode ser removido chamando <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">Configurando o Transparent Application Failover</h2>
  <p class="para">
   O TAF pode ser configurado no lado do PHP OCI8 ou na configuração
   do banco de dados. Se ambos estiverem configurados, as configurações do lado do banco de dados
   terão precedência.
  </p>
  <p class="para">
   Configure o TAF no PHP OCI8 (no lado do cliente) incluindo o
   parâmetro FAILOVER_MODE na parte CONNECT_DATA de um
   descritor de conexão. Consulte Configurando o Transparent Application
   Failover no <a href="https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-8F532535-C401-4B51-BE0B-04FD74BB0621" class="link external">&raquo;&nbsp;Guia
   do Administrador de Serviços de Rede do Oracle Database</a> para
   obter mais informações sobre a configuração do lado do cliente do TAF.
  </p>
  <p class="para">
   Um exemplo de tnsnames.ora para configurar o TAF para reconexão à
   mesma instância do banco de dados:
  </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">
   Como alternativa, configure o TAF no lado do banco de dados
   modificando o serviço de destino com
   <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) ou o procedimento empacotado
   <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
   bancos de dados de instância
   única).
  </p>
 </div>
 <div class="section">
  <h2 class="title">Usando Chamada de Retorno TAF no OCI8</h2>
  <p class="para">
   Uma chamada de retorno TAF é uma função de aplicação que pode ser
   registrada para ser chamada durante a recuperação de falha. Ela é chamada
   diversas vezes ao restabelecer a conexão da aplicação.
  </p>
  <p class="para">
   A chamada de retorno ocorre primeiro quando uma perda de conexão é detectada.
   Isso permite que a aplicação atue de acordo com o atraso
   futuro da recuperação. Se a recuperação for bem-sucedida,
   a chamada de retorno será invocada depois que a conexão for restabelecida
   e utilizável. Neste momento, a aplicação pode ressincronizar
   as configurações da sessão e executar ações como informar ao usuário
   que ocorreu uma recuperação. Se ela não for bem-sucedida, ocorrerá
   uma chamada de retorno para informar à aplicação que a recuperação não
   ocorreu e que a conexão está inutilizável.
  </p>
  <p class="para">
   A interface de uma função de retorno TAF definida pelo usuário é
   a seguinte:
  </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">
       A conexão Oracle na qual a chamada de retorno TAF foi
       registrada por meio de <span class="function"><a href="function.oci-register-taf-callback.php" class="function">oci_register_taf_callback()</a></span>.
       A conexão não é válida até que a
       recuperação seja concluída com êxito.
      </p>
     </dd>
    
    
     <dt><code class="parameter">event</code></dt>
     <dd>
      <p class="para">
       O evento de recuperação indica o status atual da
       recuperação.
      </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
          a recuperação detectou uma conexão perdida e a recuperação
          está iniciando.
         </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 conclusão
          de recuperação com sucesso.
         </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
          a recuperação não foi bem-sucedida e que não há opção
          de uma nova tentativa.
         </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> também indica
          que a recuperação não foi bem-sucedida mas dá à
          aplicação a oportunidade de lidar com o erro
          e retornar OCI_FO_RETRY para tentar a recuperação novamente.
         </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 um usuário Oracle foi re-autenticado.
         </p>
        </li>
       </ul>
      </p>
     </dd>
    
    
     <dt><code class="parameter">type</code></dt>
     <dd>
      <p class="para">
       O tipo da recuperação. Isto permite que a função de retorno saiba que
       tipo de recuperação a aplicação solicitou. Os
       valores usuais são os seguintes:
      </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
          o usuário solicitou recuperação apenas de sessão. Por
          exemplo, se uma conexão de usuário é perdida, uma
          nova sessão é automaticamente criada para o usuário
          no backup. Este tipo de recuparação não tenta
          recuperar SELECTs.
         </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
          o usuário também solicitou recuperação SELECT.
          Isto permite que usuários com cursores abertos continuem
          buscando dados após a falha.
         </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 os passos de
          recuperação devem 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
          a recuperação deve ser tentada novamente pelo Oracle.
          No caso de um erro durante a recuperação para uma nova
          conexão, o TAF poderá tentar novamente a recuperação.
          Normalmente, o código da aplicação deve ficar inativo por
          um tempo antes de retornar OCI_FO_RETRY.
         </p>
        </li>
       </ul>
      </p>
     </dd>
    
   </dl>
  </p>
  <div class="example" id="example-1">
   <p><strong>Exemplo #1 Registrando uma chamada de retorno 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">// Define chamda de retorno no espaço de usuário<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">" Recuperando ... Por favor aguarde\n"</span><span style="color: #007700">);<br />                </span><span style="color: #0000BB">printf</span><span style="color: #007700">(</span><span style="color: #DD0000">" Tipo de recuperação é %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">"DESCONHECIDA!"</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">// A aplicação não pode continuar usando o banco de dados<br />                </span><span style="color: #0000BB">printf</span><span style="color: #007700">(</span><span style="color: #DD0000">" Recuperação abortada. Recuperação não irá ocorrer.\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">// Recuperação conclui com sucesso. Informa usuários que uma recuperação aconteceu.<br />                </span><span style="color: #0000BB">printf</span><span style="color: #007700">(</span><span style="color: #DD0000">" Recuperação concluída ... retomando os serviços\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">" Recuperando usuário ... retomando os serviços\n"</span><span style="color: #007700">);<br />                </span><span style="color: #FF8000">// Reproduz qualquer comando ALTER SESSION associados com esta conexão<br />                // por exemplo, 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">// Para de tentar se já foram feitas 20 tentativas.<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">" Erro de recuperação recebido. Aguardando...\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">// tenta a recuperação novamente<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 recuperação desconhecido: %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">// Usa uma conexão privilegiada para construir uma instrução SQL que iniciará a recuperação<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">// Registra TAFCallback para Oracle TAF<br /><br /></span><span style="color: #007700">print </span><span style="color: #DD0000">"Analisando a consulta do usuário\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 exemplo, se ocorrer uma perda de conexão neste ponto, oci_execute() detectará<br />// a perda e a recuperação será iniciada. Durante a recuperação, oci_execute() invocará<br />// a função de retorno de chamada do TAF diversas vezes. Se a recuperação for bem-sucedida,<br />// uma nova conexão será criada de forma transparente e oci_execute() continuará<br />// normalmente. As configurações da sessão de conexão podem ser redefinidas na função de<br />// retorno de chamada TAF. Se a recuperação for abortada, oci_execute() retornará um erro<br />// porque uma conexão válida não está disponível.<br /><br />// Desconecta o usuário, o que inicia a recuperação<br /></span><span style="color: #007700">print </span><span style="color: #DD0000">"Desconectando o usuário\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">"Executando a consulta do usuário\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">"Não foi possível executar a instrução: "</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">// executa outras instruções SQL com a nova conexão, se ainda for 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">Veja Também</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); ?>