0

У меня есть основная база данных (server_A), зеркальная база данных (server_B) и база данных свидетелей (server_C). Базы данных настроены для автоматического перехода на другой ресурс, т. Е. Когда сервер_A сходит или выходит из строя, сервер_B принимает на себя роль новой основной базы данных. Кворум базы данных настроен правильно, насколько мне известно.Автоматическое переключение на резервные копии нескольких подключений к зеркальной базе данных при выходе принципала

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

Проблема заключается в следующем: Когда у меня есть МНОЖЕСТВЕННЫЕ подключения к базе данных (два подключенных потока, после подключения, он получит значение в цикле), когда происходит переход на другой ресурс (остановка SQL-сервера на сервере A, поэтому сервер B возьмет на себя роль принципала), я обнаруживаю сбой подключения и уничтожаю свое соединение и пытаюсь восстановить соединение с использованием той же строки соединения:

«Driver = {собственный клиент SQL]; Server = tcp: Server_A; Failover_Partner = tcp: Server_B ; Database = SomeDatabase; Uid = SomeUser; PWD = SomePassword;»

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

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

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

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

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

+0

Возможно, что драйвер, который вы используете, не является потокобезопасным, а при использовании потоковой защиты в потоковой среде результаты не могут быть предусмотрены. –

+0

Если бы это было так, приложение не сработало бы с самого начала, не пройдя зеркальный процесс? Если бы это было безопасно для потоков, я бы предположил, что сбой произойдет при подключении нескольких раз, независимо от отказа. – Zonxwedop

+0

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

ответ

0

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

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

0

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

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

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

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

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

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

+0

Строка подключения была изменена несколькими способами в надежде, что это проблема. Я попытался возиться с параметром Network, но получил тот же результат. Я не уверен в tcp: теге на отказоустойчивом партнере, я не мог ничего найти на этом, но он делает то же самое, что и остальные. Btw, тег tcp: потому что именованные каналы отключены, и мне не нужно иметь дело с именованным тайм-аутом, когда он не включен в первую очередь. Наконец, я попытался установить более длительный тайм-аут и установить короткий тайм-аут соединения и партнера по отказоустойчивости без везения. – Zonxwedop