TAF - это механизм базы данных Oracle обеспечивающий высокую доступность. Он позволяет приложениям PHP использующим OCI8 автоматически переподключаться к резервной базе данных в случае сбоя на основной или при сетевых проблемах..
В сконфигурированной системе базы данных Oracle, TAF происходит когда приложение PHP определяет, что инстанс базы данных недоступен. В этом случае происходит соединение с другим узлом в Oracle » RAC. Это может быть горячий резерв или тот же самый инстанс базы данных. Более подробно о OCI TAF читайте в » Oracle Call Interface Programmer's Guide.
Функцию обратного вызова для приложения можно зарегистрировать с помощью oci_register_taf_callback(). В процессе восстановления после отказа исполнение приложения будет приостановлено и будет вызвана зарегистрированная функция обратного вызова. Эта функция будет оповещать приложение о событиях процесса восстановления. Если восстановление завершилось успешно, управление будет возвращено приложению. Если восстановление завершилось неудачно, то все последующие обращения к базе данных будут завершаться с ошибкой, так как отсутствует подключение.
Когда соединение переходит к другой базе данных, обратный вызов может сбросить любое необходимое состояние соединения, к примеру перевыполнить любую необходимую команду ALTER SESSION если для сервиса базы данных не включен -failover_restore.
Регистрацию функции обратного вызова можно удалить с помощью oci_unregister_taf_callback().
TAF можно настроить на стороне PHP OCI8 или в конфигурации базы данных. Если настроено и там и там, то предпочтение отдается настройкам на стороне базы данных.
Настроить TAF в PHP OCI8 (на стороне клиента) можно добавив параметр FAILOVER_MODE в часть CONNECT_DATA дескриптора соединения. Более подробно о настройке TAF на стороне клиента читайте в » Oracle Database Net Services Administrator's Guide.
Пример настройки TAF в tnsnames.ora для переподключения к той же самой БД:
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))))
Также можно настроить TAF на стороне базы данных путем модификации сервиса с помощью » srvctl (для RAC) или с помощью пакетной процедуры » DBMS_SERVICE.MODIFY_SERVICE (для одиночных инстансов баз данных).
Функция обратного вызова TAF являются функцией зарегистрированной из приложения для запуска в процессе восстановления после сбоя. При восстановлении соединения она вызывается несколько раз.
Первый раз она запускается в момент обнаружения проблем с соединением. Это позволяет приложению корректно подготориться к задержке выполнения на время восстановления после сбоя. Если восстановление завершилось удачно, функция будет вызвана сразу после восстановления подключения. Этот запуск приложение может использовать для пересинхронизации настроек сессии и оповещения пользователя о том, что произошло восстановление после сбоя. Если восстановление завершилось неудачно, функция запускается еще раз для оповещения приложения о том, что восстановление завершилось с ошибкой и соединение с БД недоступно.
Интерфейс функции обратного вызова TAF:
$connection
, int $event
, int $type
) : int
connection
Идентификатор соединения Oracle для которого эта функция была зарегистрирована с помощью oci_register_taf_callback(). Соединение недоступно во время аварийного восстановления.
event
Событие восстановления означает текущий статус восстановления.
OCI_FO_BEGIN
означает, что произошла потеря
соединения и процесс восстановления начат.
OCI_FO_END
означает удачное восстановление соединения.
OCI_FO_ABORT
означает, что восстановление завершилось
неудачно и попыток восстановления больше не будет.
OCI_FO_ERROR
также означает, что восстановление
завершилось с ошибкой, но приложению дается возможность обарботать
ошибку и вернуть OCI_FO_RETRY для еще одной попытки восстановления.
OCI_FO_REAUTH
означает, что пользователь
Oracle был повторно аутентифицирован..
type
Тип восстановления после отказа. Это позволяет функции понять, какой тип восстановления запрошен приложением. Допустимы такие значения:
OCI_FO_SESSION
означает, что пользователь
запросил только восстановление сессии. К примеру, если соединение пропало,
то будет создана новая сессия на резервном сервере. Этот тип восстановления
не будет пытаться восстановить запросы типа SELECT.
OCI_FO_SELECT
означает, что запрошено восстановление
запросов SELECT. Это позволит использовать открытый курсор для
извлечения значений после восстановления.
return value
0
означает, что шаги восстановления после отказа должны
продолжаться нормально.
OCI_FO_RETRY
означает, что необходимо попробвать
восстановиться еще раз. В случае ошибки при переходе на новое соединение TAF
может повторить переход на другой ресурс. Обычно перед возвращением кода
OCI_FO_RETRY рекомендуется некоторое время подождать.
Пример регистрации функции обартного вызова TAF
<?php
// Определяем функцию обратного вызова в пространстве пользователя
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");
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;
}
}
$conn = oci_connect('hr', 'welcome', 'localhost/XE');
$fn_name = 'MyClass::TAFCallback';
oci_register_taf_callback($conn, $fn_name); // Регистрируем TAFCallback для Oracle TAF
$sql = "SELECT col1 FROM mytab";
$stmt = oci_parse($conn, $sql);
oci_define_by_name($stmt, 'COL1', $col1);
// К примеру, если соединение было потеряно на этом шаге, oci_execute()
// определит это и запустит процедуру восстановления. В процессе восстановления
// oci_execute() будет вызовать зарегистрированную функцию обратного вызова
// несколько раз. Если восстановление пройдет успешно, то будет создано новое соединение
// и выполнение oci_execute() будет продолжено в нормальном режиме.
// Настройки сессии могут быть сброшены в функции обратного вызова.
// Если восстановление завершится неудачно, oci_execute() вернет ошибку, так как
// будет отсутствовать соединение.
$e = oci_execute($stmt);
if ($e == false)
{
// обрабатываем ошибку. Если oci_execute() завершается с ошибкой то
// var_dump(oci_error($stmt));
}
while (oci_fetch($stmt))
{
echo "COL1 value is $col1<br>\n";
}
// выполняем другие SQL-запросы на новом подключении
// $stmt = oci_parse($conn, . . .);
?>