<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <title>OCI8 Transparent Application Failover (TAF) Support</title> </head> <body><div class="manualnavbar" style="text-align: center;"> <div class="prev" style="text-align: left; float: left;"><a href="oci8.fan.html">OCI8 Fast Application Notification (FAN) Support</a></div> <div class="next" style="text-align: right; float: right;"><a href="oci8.dtrace.html">OCI8 and DTrace Dynamic Tracing</a></div> <div class="up"><a href="book.oci8.html">OCI8</a></div> <div class="home"><a href="index.html">PHP Manual</a></div> </div><hr /><div id="oci8.taf" class="chapter"> <h1>OCI8 Transparent Application Failover (TAF) Support</h1> <div class="section"> <p class="para"> TAF is an Oracle Database feature that provides high availability. It enables PHP OCI8 applications to automatically reconnect to a preconfigured database when database connectivity fails due to instance or network failure. </p> <p class="para"> In a configured Oracle Database system, TAF occurs when the PHP application detects that the database instance is down or unreachable. It establishes a connection to another node in an Oracle <a href="http://docs.oracle.com/database/122/RACAD/ensuring-application-continuity.htm#RACAD-GUID-DEF850F6-27E9-428E-B8FC-530230D78AD2" class="link external">» RAC</a> configuration, a hot standby database, or the same database instance itself. See <a href="http://docs.oracle.com/database/122/LNOCI/oci-programming-advanced-topics.htm#LNOCI16675" class="link external">» Oracle Call Interface Programmer's Guide</a> for more information about OCI TAF. </p> <p class="para"> An application callback can be registered with <span class="function"><a href="function.oci-register-taf-callback.html" class="function">oci_register_taf_callback()</a></span>. During failover, normal application processing stops and the registered callback is invoked. The callback notifies the application of the failover events. If the failover succeeds, normal processing will be resumed. If the failover aborts, any following database operations in the application will fail due to no connection being available. </p> <p class="para"> When a connection fails over to another database, the callback can reset any necessary connection state, for example replaying any necessary ALTER SESSION commands if the database service did not have -failover_restore enabled. </p> <p class="para"> An application callback can be removed by calling <span class="function"><a href="function.oci-unregister-taf-callback.html" class="function">oci_unregister_taf_callback()</a></span>. </p> </div> <div class="section"> <h2 class="title">Configuring Transparent Application Failover</h2> <p class="para"> TAF can be configured on the PHP OCI8 side or in the database configuration. If both are configured, database-side settings take precedence. </p> <p class="para"> Configure TAF in PHP OCI8 (the client side) by including the FAILOVER_MODE parameter in the CONNECT_DATA portion of a connect descriptor. See Configuring Transparent Application Failover in <a href="http://docs.oracle.com/database/122/NETAG/enabling-advanced-features.htm#NETAG338" class="link external">» Oracle Database Net Services Administrator's Guide</a> for more information about client side configuration of TAF. </p> <p class="para"> An example tnsnames.ora to configure TAF reconnecting to the same database instance: </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 = orcl) (FAILOVER_MODE = (TYPE = SELECT) (METHOD = BASIC) (RETRIES = 20) (DELAY = 15)))) </pre></div> </div> </div> </p> <p class="para"> Alternatively configure TAF on the database side by modifying the target service with <a href="http://docs.oracle.com/database/122/RACAD/workload-management-with-dynamic-database-services.htm#RACAD076" class="link external">» srvctl</a> (for RAC) or the <a href="http://docs.oracle.com/database/122/ARPLS/DBMS_SERVICE.htm#ARPLS092" class="link external">» DBMS_SERVICE.MODIFY_SERVICE</a> packaged procedure (for single instance databases). </p> </div> <div class="section"> <h2 class="title">Using TAF Callbacks in OCI8</h2> <p class="para"> A TAF callback is an application function that can be registered to be called during failover. It is called several times while re-establishing the application's connection. </p> <p class="para"> Callback first occurs when a loss of connection is detected. This allows the application to act accordingly for the upcoming delay of the failover. If the failover is successful, the callback is invoked after connection is re-established and usable. At this time, the application can resynchronize session settings and take actions such as informing the user that failover occurred. If failover is unsuccessful, a callback occurs to inform the application that a failover did not take place and the connection is unusable. </p> <p class="para"> The interface of a TAF user-defined callback function is as follows: </p> <div class="methodsynopsis dc-description"> <span class="type">int</span> <span class="methodname"><strong>userCallbackFn</strong></span> ( <span class="methodparam"><span class="type">resource</span> <code class="parameter">$connection</code></span> , <span class="methodparam"><span class="type">int</span> <code class="parameter">$event</code></span> , <span class="methodparam"><span class="type">int</span> <code class="parameter">$type</code></span> )</div> <p class="para"> <dl> <dt> <code class="parameter">connection</code></dt> <dd> <p class="para"> The Oracle connection on which the TAF callback was registered via <span class="function"><a href="function.oci-register-taf-callback.html" class="function">oci_register_taf_callback()</a></span>. The connection is not valid until the failover completes successfully. </p> </dd> <dt> <code class="parameter">event</code></dt> <dd> <p class="para"> The failover event indicates the current status of the failover. </p> <p class="para"> <ul class="itemizedlist"> <li class="listitem"> <p class="para"> <strong><code>OCI_FO_BEGIN</code></strong> indicates that failover has detected a lost connection and failover is starting. </p> </li> <li class="listitem"> <p class="para"> <strong><code>OCI_FO_END</code></strong> indicates successful completion of failover. </p> </li> <li class="listitem"> <p class="para"> <strong><code>OCI_FO_ABORT</code></strong> indicates that failover was unsuccessful, and there is no option of retrying. </p> </li> <li class="listitem"> <p class="para"> <strong><code>OCI_FO_ERROR</code></strong> also indicates that failover was unsuccessful, but it gives the application the opportunity to handle the error and return OCI_FO_RETRY to retry failover. </p> </li> <li class="listitem"> <p class="para"> <strong><code>OCI_FO_REAUTH</code></strong> indicates that an Oracle user has been re-authenticated. </p> </li> </ul> </p> </dd> <dt> <code class="parameter">type</code></dt> <dd> <p class="para"> The failover type. This lets the callback know what type of failover the application has requested. The usual values are as follows: </p> <p class="para"> <ul class="itemizedlist"> <li class="listitem"> <p class="para"> <strong><code>OCI_FO_SESSION</code></strong> indicates that the user has requested only session failover. For example, if a user's connection is lost, then a new session is automatically created for the user on the backup. This type of failover does not attempt to recover SELECTs. </p> </li> <li class="listitem"> <p class="para"> <strong><code>OCI_FO_SELECT</code></strong> indicates that the user has requested SELECT failover as well. It allows users with open cursors to continue fetching from them after failure. </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"> <strong><code>0</code></strong> indicates the failover steps should continue normally. </p> </li> <li class="listitem"> <p class="para"> <strong><code>OCI_FO_RETRY</code></strong> indicates that the failover should be attempted again by Oracle. In case of an error while failing over to a new connection, TAF is able to retry the failover. Typically, the application code should sleep for a while before returning OCI_FO_RETRY. </p> </li> </ul> </p> </dd> </dl> </p> <div class="example" id="example-2423"> <div class="example-contents"><p> The following example registers a TAF callback </p></div> <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"> <span style="color: #0000BB"><?php<br /><br /></span><span style="color: #FF8000">// Define userspace callback<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">" Failing Over ... Please stand by"</span><span style="color: #007700">);<br /> </span><span style="color: #0000BB">printf</span><span style="color: #007700">(</span><span style="color: #DD0000">" Failover type was found to be %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"<br /> </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">// The application cannot continue using the database<br /> </span><span style="color: #0000BB">printf</span><span style="color: #007700">(</span><span style="color: #DD0000">" Failover aborted. Failover will not take place.\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">// Failover completes successfully. Inform users a failover occurs.<br /> </span><span style="color: #0000BB">printf</span><span style="color: #007700">(</span><span style="color: #DD0000">" Failover ended ... resuming services\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">" Failed over user ... resuming services\n"</span><span style="color: #007700">);<br /> </span><span style="color: #FF8000">// Replay any ALTER SESSION commands associated with this connection<br /> // eg. 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">// Stop retrying if we have already attempted for 20 times.<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">>= </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">" Failover error received. Sleeping...\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">// retry failover<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">"Bad Failover Event: %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">$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">'localhost/XE'</span><span style="color: #007700">);<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">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">// Register TAFCallback to Oracle TAF <br /><br /></span><span style="color: #0000BB">$sql </span><span style="color: #007700">= </span><span style="color: #DD0000">"SELECT col1 FROM mytab"</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 /></span><span style="color: #0000BB">oci_define_by_name</span><span style="color: #007700">(</span><span style="color: #0000BB">$stmt</span><span style="color: #007700">, </span><span style="color: #DD0000">'COL1'</span><span style="color: #007700">, </span><span style="color: #0000BB">$col1</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">// For example, if a connection loss occurs at this point, oci_execute() will<br />// detect the loss and failover begins. During failover, oci_execute() will<br />// invoke the TAF callback function several times. If the failover is successful,<br />// a new connection is transparently created and oci_execute() will continue as<br />// usual. The connection session settings can be reset in the TAF callback<br />// function. If the failover is aborted, oci_execute() will return an error <br />// because a valid connection is not available.<br /><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">== </span><span style="color: #0000BB">false</span><span style="color: #007700">)<br />{<br /> </span><span style="color: #FF8000">// do error handling, if oci_execute() fails<br /> // var_dump(oci_error($stmt));<br /></span><span style="color: #007700">}<br />while (</span><span style="color: #0000BB">oci_fetch</span><span style="color: #007700">(</span><span style="color: #0000BB">$stmt</span><span style="color: #007700">))<br />{<br /> echo </span><span style="color: #DD0000">"COL1 value is </span><span style="color: #0000BB">$col1</span><span style="color: #DD0000"><br>\n"</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #FF8000">// do other SQL statements with the new connection, if it is valid<br />// $stmt = oci_parse($conn, . . .); <br /><br /></span><span style="color: #0000BB">?></span> </span> </code></div> </div> </div> </div> <div class="section"> <h2 class="title">See Also</h2> <ul class="simplelist"> <li class="member"><span class="function"><a href="function.oci-register-taf-callback.html" class="function">oci_register_taf_callback()</a></span></li> <li class="member"><span class="function"><a href="function.oci-unregister-taf-callback.html" class="function">oci_unregister_taf_callback()</a></span></li> </ul> </div> </div> <hr /><div class="manualnavbar" style="text-align: center;"> <div class="prev" style="text-align: left; float: left;"><a href="oci8.fan.html">OCI8 Fast Application Notification (FAN) Support</a></div> <div class="next" style="text-align: right; float: right;"><a href="oci8.dtrace.html">OCI8 and DTrace Dynamic Tracing</a></div> <div class="up"><a href="book.oci8.html">OCI8</a></div> <div class="home"><a href="index.html">PHP Manual</a></div> </div></body></html>