Эта статья о том как работать с восстановлением соединения при нестабильной сети и обрывающемся подключении, при перезагрузке сервера базы данных и так далее.
Основа для этой статьи – официальная документация
FireDAC позволяет автоматически определять обрыв сети и корректно на него реагировать когда идет работа с базой данных, например, работают методы Open, ExecSQL, Ping. Драйвер DBMS (в случае MySQL libmysql.dll) возбуждает исключение EADDBEngineException со свойством Kind = ekServerGone.
Все типы ошибок можно посмотреть в модуле FireDAC.Stan.Error
1 2 3 4 |
TFDCommandExceptionKind = (ekOther, ekNoDataFound, ekTooManyRows, ekRecordLocked, ekUKViolated, ekFKViolated, ekObjNotExists, ekUserPwdInvalid, ekUserPwdExpired, ekUserPwdWillExpire, ekCmdAborted, <strong>ekServerGone</strong>, ekServerOutput, ekArrExecMalfunc, ekInvalidParams); |
Наиболее простой способ проверить соединение с DBMS это применить метод TFDCustomConnection.Ping
Далее, в документации идет список известных ограничений
Меня заинтересовали ограничения MySQL, поскольку я работаю с этой базой. Данные параметры можно настроить при создании / настройке ConnectionDefinition. Список параметров можно посмотреть по этой ссылке.
Управление Автовосстановлением
Чтобы автовосстановление происходило автоматически, необходимо ResourceOptions.AutoReconnect поставить в True. Опционально FireDAC имеет 3 обработчика для AutoReconnect
- OnRecover – ловит обрыв соединения и говорит FireDAC что делать дальше;
- OnLosted – -ловит обрыв и говорит что делать FireDAC, если у него не получилось автоматически обработать
- OnRestored – ловит обрыв и срабатывает после успешного восстановления.
OnRecover можно использовать, например, для перевода FireDAC в оффлайн режим или для того, чтобы просто закрыть соединение. Когда событие OnRecover не обработано, то FireDAC пробует восстановить соединение. Вот пример кода из документации
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
procedure TForm1.FDConnection1Recover(ASender: TObject; const AInitiator: IFDStanObject; AException: Exception; var AAction: TFDPhysConnectionRecoverAction); var iRes: Integer; begin iRes := MessageDlg('Connection is lost. Offline - yes, Retry - ok, Fail - Cancel', mtConfirmation, [mbYes, mbOK, mbCancel], 0); case iRes of mrYes: AAction := faOfflineAbort; mrOk: AAction := faRetry; mrCancel: AAction := faFail; end; Log('Connection is recovering'); end; |
В документации также написано, что рекомендуется не закрывать FDManager из событий OnRecover, OnLosted,OnRestored.
AAction
Это интересный параметр, с помощью него можно управлять автосоединением. Вот что написано в справке по этому поводу.
Подготовка приложения после обрыва соединения
После обрыва соединения
- Активные транзакции откатываются назад, исполнение продолжается с инструкции, на которой произошла ошибка.
- Не полученные результаты (not fetched) обрезаются и TFDDataSet.SourceEOF устанавливается в True
- состояния базы данных и сессионные переменные теряются
- Зарегистрированные события БД не регистрируются
Чтобы минимизировать потери от нестабильной сети, можно установить следующие значения
- FetchOptions.Mode to fmAll;
- FetchOptions.RowsetSize to 200-500;
- FetchOptions.AutoClose to True (default);
- TxOptions.AutoCommit to True;
- ResourceOptions.AutoReconnect to True.
Приложение может также использовать Offline connection mode и CachedUpdates