У меня есть ситуация, когда у нас есть две производственные базы данных, которые синхронизируются друг с другом. Server One считается первичным. Иногда из-за технического обслуживания или бедствия Server Two станет основным.
В некотором из нашего кода это означает, что нам нужно вручную войти и отредактировать имя сервера для соединений с базой данных. Я нахожу это раздражающим, поэтому последнее, что я написал, я помещал информацию о сервере для обоих и настраивал цикл. Если oci_connect провалился на сервере One 3 раза, он переместится на Server Two. Если Server Two провалился 3 раза, он уведомит пользователя о невозможности подключения.
Это отлично срабатывало, когда у нас была ситуация с переключением серверов. Вчера, например, он работал нормально. Сегодня этого не произошло. Он просто сидел и крутился бесконечно. Ошибка в журнале ошибок PHP. Нет отказа от перехода. На экран не выводится ошибка. Ничего в течение 5 минут.
Итак, мне пришлось вручную редактировать глупый файл конфигурации.
Я спросил, что может быть другим, и мне сказали, что вчера база данных была отключена, но не сервер. Сегодня сервер не работает ". Хорошо...? Но я не вижу различия. Я ожидал бы, что oci_connect вернет false, если не сможет установить какой-либо связи с сервером. Я ожидаю, что это будет тайм-аут и ошибка. Не просто передавать его, когда он получает код ошибки с сервера. Что, если есть сетевая проблема, например?
Является ли это ошибкой в oci_connect или есть вероятность, что что-то в нашей конфигурации PHP дает oci_connect безумно длинный тайм-аут?
Если это своего рода "ошибка", есть ли способ проверить, первым ли сервер? Как пинг? (Конечно, когда я сделал ping через командную строку, я получил ответ от Server One, а затем мне сказали "это сейчас", хотя я скептически отношусь к этому времени.)
В любом случае, если кто-то может пролить свет на то, почему oci_connect может работать бесконечно без сбоев и как его избежать, я был бы благодарен.
- Редактировать: Мой код выглядит как примеры на PHP.net только в некоторых циклах.
$count = count($servers);
for($i = 0; $i < $count; $i++){
if((!isset($connection)) || ($connection == false)){
// Attempt to connect to the oracle database
$connection = @oci_connect($servers[$i]["user"], $servers[$i]["pass"], $servers[$i]["conid"]) or ($conn_error = oracle_error());
// Try again if there was a failure
if(($connection == false) || (isset($con_error))){
// Three (two more) tries per alternative
for($j = $st; $j < $fn; $j++){
// Try again to connect
$connection = @oci_connect($servers[$i]["user"], $servers[$i]["pass"], $servers[$i]["conid"]) or ($conn_error = oracle_error());
} // for($j = 2; $j < 4; $j++)
} // if($connection == false)
} // if(!isset($connection) || ($connection == false))
} // for($i = 0; $i < $count; $i++)
Можете ли вы проверить, что он не возвращает false? Возможно, это просто блокировка при ожидании соединения? (что произойдет, если вы выполните var_dump(oci_connect(...))
?
Справа от php.net документация:
Если вы хотите указать соединение тайм-аут в случае наличия сети проблема, вы можете отредактировать клиентскую сторону (например, на стороне PHP), файл sqlnet.ora и установите SQLNET.OUTBOUND_CONNECT_TIMEOUT. Это устанавливает верхний предел для установление права подключения через БД, включая время для попыток подключения к другим Сервисы. Он доступен из Oracle 10.2.0.3 и далее.
В Oracle 11.1 немного более легкое решение Был введен TCP.CONNECT_TIMEOUT. Он также является параметром sqlnet.ora. Это ограничивает только TCP-соединение время создания, которое в основном где видны проблемы со связью.
Клиентский файл sqlnet.ora должен быть поместить в тот же каталог, что и tnsnames.ora.
Кроме того, вы можете проверить FAN на этой странице... Похоже, что он может делать именно то, что вы хотите (но У меня нет опыта в этом, поэтому я не уверен, действительно ли это подходит вам).