/
taf.xml
executable file
·373 lines (356 loc) · 12.3 KB
/
taf.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<chapter xml:id="oci8.taf" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>OCI8 Transparent Application Failover (TAF) Support</title>
<section>
<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.
</para>
<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 <link xlink:href="&url.oracle.taf.rac;">RAC</link>
configuration, a hot standby database, or the same database
instance
itself. See <link xlink:href="&url.oracle.taf.ociguide;">Oracle
Call Interface Programmer's Guide</link> for more information about
OCI TAF.
</para>
<para>
An application callback can be registered
with <function>oci_register_taf_callback</function>. 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.
</para>
<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.
</para>
<para>
An application callback can be removed by calling <function>oci_unregister_taf_callback</function>.
</para>
</section>
<section>
<title>Configuring Transparent Application Failover</title>
<para>
TAF can be configured on the PHP OCI8 side or in the database
configuration. If both are configured, database-side settings
take precedence.
</para>
<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 <link xlink:href="&url.oracle.taf.clientconfig;">
Oracle Database Net Services Administrator's Guide</link> for
more information about client side configuration of TAF.
</para>
<para>
An example tnsnames.ora to configure TAF reconnecting to the
same database instance:
</para>
<para>
<informalexample>
<screen>
<![CDATA[
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))))
]]>
</screen>
</informalexample>
</para>
<para>
Alternatively configure TAF on the database side by
modifying the target service with
<link xlink:href="&url.oracle.taf.srvctl;">srvctl</link>
(for RAC) or the
<link xlink:href="&url.oracle.taf.dbmsservice;">
DBMS_SERVICE.MODIFY_SERVICE</link> packaged procedure
(for single instance databases).
</para>
</section>
<section>
<title>Using TAF Callbacks in OCI8</title>
<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.
</para>
<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.
</para>
<para>
The interface of a TAF user-defined callback function is as
follows:
</para>
<methodsynopsis>
<type>int</type><methodname>userCallbackFn</methodname>
<methodparam><type>resource</type><parameter>connection</parameter></methodparam>
<methodparam><type>int</type><parameter>event</parameter></methodparam>
<methodparam><type>int</type><parameter>type</parameter></methodparam>
</methodsynopsis>
<para>
<variablelist>
<varlistentry>
<term><parameter>connection</parameter></term>
<listitem>
<para>
The Oracle connection on which the TAF callback was
registered via <function>oci_register_taf_callback</function>.
The connection is not valid until the
failover completes successfully.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>event</parameter></term>
<listitem>
<para>
The failover event indicates the current status of
the failover.
</para>
<para>
<itemizedlist>
<listitem>
<para>
<constant>OCI_FO_BEGIN</constant> indicates that
failover has detected a lost connection and failover
is starting.
</para>
</listitem>
<listitem>
<para>
<constant>OCI_FO_END</constant> indicates successful
completion of failover.
</para>
</listitem>
<listitem>
<para>
<constant>OCI_FO_ABORT</constant> indicates that
failover was unsuccessful, and there is no option
of retrying.
</para>
</listitem>
<listitem>
<para>
<constant>OCI_FO_ERROR</constant> 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.
</para>
</listitem>
<listitem>
<para>
<constant>OCI_FO_REAUTH</constant> indicates
that an Oracle user has been re-authenticated.
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>type</parameter></term>
<listitem>
<para>
The failover type. This lets the callback know what
type of failover the application has requested. The
usual values are as follows:
</para>
<para>
<itemizedlist>
<listitem>
<para>
<constant>OCI_FO_SESSION</constant> 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.
</para>
</listitem>
<listitem>
<para>
<constant>OCI_FO_SELECT</constant> indicates that
the user has requested SELECT failover as well.
It allows users with open cursors to continue
fetching from them after failure.
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>return value</parameter></term>
<listitem>
<para>
<itemizedlist>
<listitem>
<para>
<literal>0</literal> indicates the failover
steps should continue normally.
</para>
</listitem>
<listitem>
<para>
<constant>OCI_FO_RETRY</constant> 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.
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<example>
<para>
The following example registers a TAF callback
</para>
<programlisting role="php">
<![CDATA[
<?php
// Define userspace callback
class MyClass {
public static $retry_count;
public static function TAFCallback($conn, $event, $type)
{
switch ($event) {
case OCI_FO_BEGIN:
printf(" Failing Over ... Please stand by\n");
printf(" Failover type was found to be %s \n",
(($type==OCI_FO_SESSION) ? "SESSION"
:(($type==OCI_FO_SELECT) ? "SELECT" : "UNKNOWN!")));
self::$retry_count = 0;
break;
case OCI_FO_ABORT:
// The application cannot continue using the database
printf(" Failover aborted. Failover will not take place.\n");
break;
case OCI_FO_END:
// Failover completes successfully. Inform users a failover occurs.
printf(" Failover ended ... resuming services\n");
break;
case OCI_FO_REAUTH:
printf(" Failed over user ... resuming services\n");
// Replay any ALTER SESSION commands associated with this connection
// eg. oci_parse($conn, ‘ALTER SESSION …’) ;
break;
case OCI_FO_ERROR:
// Stop retrying if we have already attempted for 20 times.
if (self::$retry_count >= 20)
return 0;
printf(" Failover error received. Sleeping...\n");
sleep(10);
self::$retry_count++;
return OCI_FO_RETRY; // retry failover
break;
default:
printf("Bad Failover Event: %d.\n", $event);
break;
}
return 0;
}
}
$fn_name = 'MyClass::TAFCallback';
$conn = oci_connect('hr', 'welcome', 'orcl');
$sysconn = oci_connect('system', 'oracle', 'orcl');
// Use a privileged connection to construct a SQL statement that will initiate failover
$sql = <<< 'END'
select unique 'alter system disconnect session '''||sid||','||serial#||''''
from v$session_connect_info
where sid = sys_context('USERENV', 'SID')
END;
$s = oci_parse($conn, $sql);
oci_execute($s);
$r = oci_fetch_array($s);
$disconnectssql = $r[0];
oci_register_taf_callback($conn, $fn_name); // Register TAFCallback to Oracle TAF
print "Parsing user query\n";
$sql = "select systimestamp from dual";
$stmt = oci_parse($conn, $sql);
// For example, if a connection loss occurs at this point, oci_execute() will
// detect the loss and failover begins. During failover, oci_execute() will
// invoke the TAF callback function several times. If the failover is successful,
// a new connection is transparently created and oci_execute() will continue as
// usual. The connection session settings can be reset in the TAF callback
// function. If the failover is aborted, oci_execute() will return an error
// because a valid connection is not available.
// Disconnect the user, which initiates failover
print "Disconnecting the user\n";
$discsql = oci_parse($sysconn, $disconnectssql);
oci_execute($discsql);
print "Executing user query\n";
$e = oci_execute($stmt);
if (!$e) {
$m = oci_error($stmt);
trigger_error("Could not execute statement: ". $m['message'], E_USER_ERROR);
}
$row = oci_fetch_array($stmt);
print $row[0] . "\n";
// do other SQL statements with the new connection, if it is valid
// $stmt = oci_parse($conn, . . .);
?>
]]>
</programlisting>
</example>
</section>
<section>
&reftitle.seealso;
<simplelist>
<member><function>oci_register_taf_callback</function></member>
<member><function>oci_unregister_taf_callback</function></member>
</simplelist>
</section>
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->