Delphi.FireDAC. Многопоточность

Данная статья посвящена многопоточному режиму FireDAC. Она основана на официальной документации.

-старая версия

-новая версия

FireDAC потокобезопасен, если выполняются следующие условия

-FDConnection и все ассоциированные с ним объекты (такие как FDQuery, FDTransaction и так далее) используются в одном потоке в каждый момент.

-FDManager активирован до того как потоки начали свою работу. Свойство FDManager.Active поставлено в True

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

Такой подход может создать проблемы. Можно, например, получить ошибки «Connection is busy with results for another command» и др.

Решение проблемы — использовать для каждого потока свое соединение (FDConnection), которое работает с DBMS. Например, таким образом… (далее в документации приводится такой пример)

Замечание. Для выше приведенного случая, где приложение запускает одиночный SQL запрос (in background) рекомендуется использовать асинхронный режим (asynchronous query execution mode).

Замечание.  Многопоточное приложение может закрывать соединения, открытые в background threads. Можно использовать событие TFDManager.BeforeShutdown, чтобы это предотвратить.

Пулы соединений (Connection Pooling)

Одно из самых затратных взаимодействий с БД, с точки зрения вычислительных ресурсов это установка соединения (the connection establishment). В многопоточном приложении, где каждый поток стартует, устанавливает соединение, выполняет некоторую работу и освобождает соединение, повторяющиеся установки соединения могут привести к деградации производительности всей системы. Чтобы избежать этого — можно использовать пулы соединений.

Пулы соединений могут быть использованы только для ersistent or private connection definition, при помощи установки в True параметра Pooled. (Pooled=True)

Пример для PersistentDefinition

Или пример для PrivateDefinition

Никаких дополнительных параметров не может быть в свойстве TFDConnection.Params, потому что все соединения, находящиеся в пуле должны обладать одними и теми же параметрами.

Устанавливая свойство TFDConnection.Connected в True мы даем команду пулу соединений физически соединиться с БД.

Устанавливая свойство TFDConnection.Connected в False, мы отсоединяем FDConnection от пула, но оставляем соединение пула с БД открытым. Чтобы закрыть и уничтожить все соединения пула, приложение может вызвать метод TFDManager.CloseConnectionDef.

Либо можно закрыть FDManager

Для пула соединений могут быть настроены следующие дополнительные параметры

19

 

POOL_CleanupTimeout — время, в течение которого FireDAC удаляет ненужные соединения (те, которые превысили время POOL_ExpireTimeout)

POOL_ExpireTimeout — время, после которого неактивные соединения могут быть удалены из пула и уничтожены. Значение по умолчанию 90000 милисекунд (90 сек.)

POOL_Maximumitems — максимальное значение пула. Когда приложение требует больше соединений, выскакивает исключение. Значение по умолчанию 50.