Автоматическое аварийное переключение нескольких подключений к зеркальной базе данных при выходе из строя основной базы данных.

У меня есть основная база данных (server_A), зеркальная база данных (server_B) и база данных-свидетель (server_C). Базы данных настроены на автоматическое переключение при сбое, то есть, когда сервер_А выходит из строя или происходит отработка отказа, сервер_В берет на себя роль новой основной базы данных. Насколько мне известно, кворум базы данных настроен правильно.

Я написал приложение на С++ для подключения к базе данных и получения значения для обеспечения истинного соединения. Приложение обнаруживает сбой при вызове GetValue и пытается повторно подключиться при возникновении ошибки.

Проблема заключается в следующем: когда у меня есть НЕСКОЛЬКО подключений к базе данных (два потока подключены, после подключения он получит значение в цикле), когда происходит отработка отказа (остановка сервера sql на сервере A, чтобы сервер B стал основным ), я обнаруживаю сбой соединения, разрушаю свое соединение и пытаюсь восстановить соединение, используя ту же строку соединения:

"Driver={SQL Native Client};Server=tcp:Server_A;Failover_Partner=tcp:Server_B;Database=SomeDatabase;Uid=SomeUser;Pwd=SomePassword;"

** ПРИМЕЧАНИЕ ** Я убедился, что переход на другой ресурс произошел путем мониторинга баз данных.

Несмотря на то, что соединение с базой данных было правильно удалено, я не могу повторно подключиться к базе данных, пока не перезапущу приложение, ИЛИ если я верну server_A в оперативный режим (теперь он действует как зеркальная база данных), а затем отработку отказа server_B (отключение сервера sql ) снова сделав сервер A основной базой данных, приложение может повторно подключиться без необходимости полного закрытия.

Хотя я мог бы манипулировать строкой подключения, чтобы сделать server_B новым принципалом, а server_A новым Failover_Partner, это не идеальное решение, так как будет использоваться гораздо больше подключений.

Имейте в виду, что это происходит ТОЛЬКО при множественных подключениях к базе данных. Если я запускаю приложение только с одним соединением, все в порядке, и я могу снова подключиться, когда произойдет аварийное переключение.

РЕДАКТИРОВАТЬ: Если я сначала подключаюсь к нескольким потокам, все в порядке. Когда я завершаю работу SQL Server и, следовательно, происходит отказоустойчивость, я могу повторно подключиться только тогда, когда я прохожу и удаляю ВСЕ объекты и повторно создаю экземпляры новых объектов. Кроме того, я использую SQL Native Client 11.0 (ODBC). Мысли?


person Zonxwedop    schedule 27.08.2014    source источник
comment
Вполне может быть, что используемый вами драйвер не является потокобезопасным, а когда в многопоточной среде используется небезопасная для потоков библиотека, результаты нельзя предвидеть.   -  person Tymoteusz Paul    schedule 27.08.2014
comment
Если бы это было так, не вышло бы приложение с самого начала, не пройдя процесс зеркалирования? Если бы это не было потокобезопасным, я бы подозревал, что сбой произойдет при многократном подключении независимо от аварийного переключения.   -  person Zonxwedop    schedule 27.08.2014
comment
Может, может и нет. Очень сложно предсказать, что произойдет, когда код, не поддерживающий многопоточность, подвергается воздействию многопоточной среды.   -  person Tymoteusz Paul    schedule 27.08.2014


Ответы (2)


Многое из того, что вы описываете, согласуется с проблемой, описанной в KB 2605597 "Time-out ошибка при создании зеркального подключения к базе данных поставщиком данных .NET Framework для SQLClient».

В БЗ описаны проблемы, когда время ожидания соединения установлено на 15 секунд, я случайно слышал о подобных проблемах, когда время ожидания соединения установлено на 0 (что не является хорошей идеей по другим причинам, упомяну на всякий случай).

Это исправление применяется к серверам приложений. Если вы хотите исключить это как возможную причину, вы можете проверить увеличение тайм-аута (как указано в разделах обходного пути поста), чтобы убедиться, что это не проблема.

Позже подумал: Еще одна вещь, которую я заметил, необычна, это то, что вы указываете протокол TCP в строке подключения и имени партнера по отработке отказа. Из документации мне не ясно, поддерживается ли это в имени партнера по отработке отказа. Возможно, вы захотите попробовать удалить это и вместо этого указать сетевой атрибут. (рекомендуется здесь.)

Я понимаю, что вы считаете, что проблема заключается не в этих вещах из-за проблемы с одним или несколькими соединениями, которую вы тестировали.

Тем не менее, я думаю, вам лучше упростить строку подключения, чтобы она как можно больше соответствовала опубликованным примерам и убедиться, что это не проблемы, с которыми люди обычно сталкиваются в первую очередь. (Проблема с повторной попыткой возникает, когда есть задержка, что может сделать ее несколько спорадической.)

person kendra    schedule 27.08.2014
comment
Предоставленная строка подключения была изменена несколькими способами в надежде, что проблема была в ней. Я пробовал возиться с параметром сети, но все равно получил тот же результат. Я также не уверен в теге tcp: на партнере по отработке отказа, я ничего не мог найти по этому поводу, но он делает то же самое, что и остальные. Кстати, тег tcp: связан с тем, что именованные каналы отключены, и мне не нужно иметь дело с тайм-аутом именованных каналов, когда он изначально не включен. Наконец, я попытался установить более длительный тайм-аут и установить короткий тайм-аут для соединения и партнера по отработке отказа, но безуспешно. - person Zonxwedop; 28.08.2014

Хорошо, я нашел ответ.

Мне пришлось изменить файл hosts, потому что мое приложение не находилось в том же домене, что и базы данных. Поэтому при попытке выполнить отработку отказа я не смог получить доступ к базе данных с именем экземпляра (именно так кэшировался партнер по отработке отказа). Я изменил файл hosts, чтобы преобразовать имя экземпляра в IP-адрес машины, и теперь все работает.

person Zonxwedop    schedule 10.09.2014