mirror of
https://github.com/php/doc-ru.git
synced 2025-07-20 16:42:29 +00:00
353 lines
18 KiB
XML
353 lines
18 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
||
<!-- EN-Revision: f4c44b86948f70a7e89f582b500e2595452e00f0 Maintainer: rjhdby Status: ready -->
|
||
<!-- Reviewed: no -->
|
||
<chapter xml:id="oci8.taf" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||
<title>Поддержка прозрачного для приложений восстановления после отказа (Transparent Application Failover или TAF) для OCI8</title>
|
||
<para>
|
||
TAF — функция базы данных Oracle, которая обеспечивает высокую доступность.
|
||
TAF помогает OCI8-приложениям PHP автоматически переподключаться
|
||
к предварительно настроенной базе данных при сбое подключения к базе данных
|
||
из-за сбоя экземпляра или сети.
|
||
</para>
|
||
<para>
|
||
В сконфигурированной системе базы данных Oracle TAF-обработка происходит, когда
|
||
PHP-приложение обнаруживает, что экземпляр базы данных не работает или недоступен.
|
||
Он устанавливает соединение с другим узлом в конфигурации
|
||
Oracle <link xlink:href="&url.oracle.taf.rac;">RAC</link>, базой данных горячего
|
||
резерва или самим экземпляром базы данных. Подробнее об OCI TAF
|
||
рассказывает краткое руководство <link xlink:href="&url.oracle.taf.ociguide;">Oracle
|
||
Call Interface Programmer's Guide</link>.
|
||
</para>
|
||
<para>
|
||
Callback-функцию приложения регистрируют функцией
|
||
<function>oci_register_taf_callback</function>. В процессе восстановления после
|
||
отказа исполнение приложения приостанавливается и вызывается зарегистрированная
|
||
callback-функция. Эта функция будет оповещать приложение о событиях
|
||
процесса восстановления. Если восстановление завершилось успешно, управление
|
||
возвращается приложению. Если восстановление завершилось неудачно, то очередные
|
||
обращения к базе данных завершаются с ошибкой, поскольку отсутствует подключение.
|
||
</para>
|
||
<para>
|
||
Когда соединение переходит к другой базе данных, обратный вызов может сбросить
|
||
любое необходимое состояние соединения, например, перевыполнить
|
||
необходимую команду ALTER SESSION, если для сервиса базы данных не включили параметр
|
||
-failover_restore.
|
||
</para>
|
||
<para>
|
||
Регистрацию callback-функции приложения удаляют вызовом функции <function>oci_unregister_taf_callback</function>.
|
||
</para>
|
||
|
||
<section>
|
||
<title>настройка TAF</title>
|
||
<para>
|
||
TAF настраивают на стороне PHP-модуля OCI8 или в конфигурации базы данных.
|
||
Если настроено и там, и там, предпочтение отдаётся настройкам на стороне базы данных.
|
||
</para>
|
||
<para>
|
||
Настроить TAF в PHP-модуле OCI8 (на стороне клиента) можно через параметр
|
||
FAILOVER_MODE в части CONNECT_DATA дескриптора соединения.
|
||
Подробнее о настройке TAF на стороне клиента рассказывает секция
|
||
«Настройка прозрачного переключения приложений при отказе» (Configuring Transparent Application Failover)
|
||
краткого руководства <link xlink:href="&url.oracle.taf.clientconfig;">
|
||
Oracle Database Net Services Administrator's Guide</link>.
|
||
</para>
|
||
<para>
|
||
Пример настройки TAF в файле tnsnames.ora для переподключения к той же самой БД:
|
||
</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>
|
||
TAF также настраивается на стороне базы данных путём изменения целевой службы
|
||
утилитой <link xlink:href="&url.oracle.taf.srvctl;">srvctl</link>
|
||
(для RAC) или через пакетную процедуру
|
||
<link xlink:href="&url.oracle.taf.dbmsservice;">
|
||
DBMS_SERVICE.MODIFY_SERVICE</link>
|
||
(для одиночных экземпляров баз данных).
|
||
</para>
|
||
</section>
|
||
<section>
|
||
<title>Callback-функции TAF в модуле OCI8</title>
|
||
<para>
|
||
Callback-функция TAF — функция приложения, которую можно зарегистрировать для вызова
|
||
во время аварийного переключения. При восстановлении соединения функция
|
||
вызывается несколько раз.
|
||
</para>
|
||
<para>
|
||
Первый раз функция запускается в момент обнаружения проблем с соединением.
|
||
Это позволяет приложению корректно подготовиться к задержке выполнения
|
||
на время восстановления после сбоя. Если восстановление завершилось успешно,
|
||
функция вызывается сразу после восстановления подключения. Этот запуск
|
||
приложение может использовать для пересинхронизации настроек сессии и оповещения
|
||
пользователя о восстановлении после сбоя. Если восстановление не удалось,
|
||
callback-функция запускается ещё раз, чтобы сообщить приложению,
|
||
что восстановление не произошло и соединение невозможно использовать.
|
||
</para>
|
||
<para>
|
||
Интерфейс callback-функции модуля TAF:
|
||
</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>
|
||
Идентификатор соединения Oracle, на котором функцией <function>oci_register_taf_callback</function>
|
||
зарегистрировали callback-функцию TAF.
|
||
Соединение недействительно, пока восстановление не завершится успешно.
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><parameter>event</parameter></term>
|
||
<listitem>
|
||
<para>
|
||
Событие восстановления означает текущий статус восстановления.
|
||
</para>
|
||
<para>
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para>
|
||
<constant>OCI_FO_BEGIN</constant> означает, что произошла потеря
|
||
соединения и процесс восстановления начат.
|
||
</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>
|
||
<constant>OCI_FO_END</constant> означает удачное восстановление соединения.
|
||
</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>
|
||
<constant>OCI_FO_ABORT</constant> означает, что восстановление завершилось
|
||
неудачно и попыток восстановления больше не будет.
|
||
</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>
|
||
<constant>OCI_FO_ERROR</constant> также означает, что восстановление
|
||
завершилось с ошибкой, но приложению даётся возможность обработать
|
||
ошибку и вернуть OCI_FO_RETRY для ещё одной попытки восстановления.
|
||
</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>
|
||
<constant>OCI_FO_REAUTH</constant> означает, что пользователь
|
||
Oracle был повторно аутентифицирован.
|
||
</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><parameter>type</parameter></term>
|
||
<listitem>
|
||
<para>
|
||
Тип восстановления после отказа. Это позволяет функции понять,
|
||
какой тип восстановления запрошен приложением. Допустимы такие значения:
|
||
</para>
|
||
<para>
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para>
|
||
<constant>OCI_FO_SESSION</constant> означает, что пользователь
|
||
запросил только восстановление сессии. К примеру, если соединение пропало,
|
||
то будет создана новая сессия на резервном сервере. Этот тип восстановления
|
||
не будет пытаться восстановить запросы типа SELECT.
|
||
</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>
|
||
<constant>OCI_FO_SELECT</constant> означает, что запрошено восстановление
|
||
запросов SELECT. Это позволит использовать открытый курсор для
|
||
извлечения значений после восстановления.
|
||
</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><parameter>return value</parameter></term>
|
||
<listitem>
|
||
<para>
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para>
|
||
<literal>0</literal> означает, что шаги восстановления после отказа должны
|
||
продолжаться нормально.
|
||
</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>
|
||
<constant>OCI_FO_RETRY</constant> означает, что необходимо попробовать
|
||
восстановиться ещё раз. В случае возникновения ошибки при переходе на новое соединение TAF
|
||
может повторить переход на другой ресурс. Обычно перед возвращением кода
|
||
OCI_FO_RETRY рекомендуется некоторое время подождать.
|
||
</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
</variablelist>
|
||
</para>
|
||
<example>
|
||
<title>Регистрация callback-функции TAF</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
// Определяем 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:
|
||
// Приложение больше не может использовать базу данных
|
||
printf(" Восстановление невозможно.\n");
|
||
break;
|
||
case OCI_FO_END:
|
||
// Восстановление завершилось успешно. Оповестим пользователей, что была проблема.
|
||
printf(" Восстановление завершено ... восстанавливаю работу\n");
|
||
break;
|
||
case OCI_FO_REAUTH:
|
||
printf(" Пользователь переавторизован ... восстанавливаю работу\n");
|
||
// Заново выполняем все необходимые ALTER SESSION
|
||
// т.е. oci_parse($conn, ‘ALTER SESSION …’) ;
|
||
break;
|
||
case OCI_FO_ERROR:
|
||
// Прекращаем попытки соединения, если их было более 20.
|
||
if (self::$retry_count >= 20)
|
||
return 0;
|
||
printf(" Ошибка восстановления. Повторная попытка через 10 секунд...\n");
|
||
sleep(10);
|
||
self::$retry_count++;
|
||
return OCI_FO_RETRY; // retry failover
|
||
break;
|
||
default:
|
||
printf("Неизвестное событие восстановления: %d.\n", $event);
|
||
break;
|
||
}
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
$fn_name = 'MyClass::TAFCallback';
|
||
|
||
$conn = oci_connect('hr', 'welcome', 'orcl');
|
||
$sysconn = oci_connect('system', 'oracle', 'orcl');
|
||
|
||
// Используйте привилегированное соединение для создания SQL-запроса, который инициирует отработку отказа
|
||
$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); // Зарегистрируйте TAFCallback для Oracle TAF
|
||
|
||
print "Разбор пользовательского запроса\n";
|
||
$sql = "select systimestamp from dual";
|
||
$stmt = oci_parse($conn, $sql);
|
||
|
||
// Например, если соединение было потеряно на этом шаге, функция oci_execute()
|
||
// определит это и запустит процедуру восстановления. В процессе восстановления
|
||
// функция oci_execute() будет вызывать зарегистрированную callback-функцию
|
||
// несколько раз. Если восстановление пройдёт успешно, callback-функция создаст новое соединение
|
||
// и выполнение функции oci_execute() продолжится в нормальном режиме.
|
||
// Настройки сессии могут быть сброшены в callback-функции.
|
||
// Если восстановление завершится неудачно, функция oci_execute() вернёт ошибку,
|
||
// поскольку будет отсутствовать соединение.
|
||
|
||
// Отключите пользователя, который инициирует аварийное переключение
|
||
print "Отключение пользователя\n";
|
||
$discsql = oci_parse($sysconn, $disconnectssql);
|
||
oci_execute($discsql);
|
||
|
||
print "Выполнение пользовательского запроса\n";
|
||
$e = oci_execute($stmt);
|
||
if (!$e) {
|
||
$m = oci_error($stmt);
|
||
trigger_error('Не удалось выполнить условие:'. $m['message'], E_USER_ERROR);
|
||
}
|
||
$row = oci_fetch_array($stmt);
|
||
print $row[0] . "\n";
|
||
|
||
// Выполняем другие SQL-запросы на новом подключении
|
||
// $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
|
||
-->
|