Em uma aplicação multithread, uma boa prática é isolar os componentes de acesso ao banco de dados, a violação dessa prática pode gerar erros do tipo access violation entre outros erros. Para ajudar a resolver esse problema, a Embarcadero disponibilizou o componente, FDManager, que é responsável pela definição e gerenciamento das conexões e é thread-safe(utilização segura em ambientes multithread).
Fonte: https://docwiki.embarcadero.com/RADStudio/Sydney/en/Multithreading_(FireDAC)
Vantagens do uso do FDManager
Definição da biblioteca cliente de acesso ao banco de dados. [OPCIONAL]
Centralização das configurações de conexão com o banco de dados.
Centralização das parametrizações do componente TFDConnection. (Esta configuração se estende para todos os FDConnection usado na aplicação)
Além do uso do FDManger uma boa prática e o uso da técnica de otimização de conexão com o banco de dados, chamado de pool de conexões.
Quando precisamos realizar qualquer operação sobre um banco de dados é primeiramente necessário estabelecer uma conexão com ele, o estabelecimento dessa conexão costuma ocorrer através do protocolo TCP/IP, envolvendo custo de abertura e fechamento da conexão. Esse custo é particularmente significativo em aplicações Web onde você pode ter um fluxo de milhares de requisições constante, e cada uma delas vai gerar a abertura e fechamento da conexão com o banco de dados. Uma técnica simples para evitar esse constante "abre-fecha" de conexões é manter um determinado número de conexões sempre aberta (um pool de conexões) e simplesmente reutilizar quando necessário, dessa forma você diminui tanto o gasto de recurso da máquina quanto o tempo de resposta da sua aplicação.
Esse custo para estabelecer uma conexão com o banco de dados pode ser visto na imagem abaixo, utilizando a ferramenta WireShark podemos ver a quantidade de pacotes que é utlizado para executar um simples select.
Podemos ver na imagem abaixo o comportamento das consultas ao banco de dados usando pool de conexões:
Para configurar um pool de conexões utilizaremos o FDManager, e as propriedades de pool.
| Parâmetro | Descrição | Exemplo |
|---|---|---|
| Pooled | Ativa o pool de conexões para um ConnectionDefName informado em FDManager.ConnectionDefs. Para usar um pool de conexões, a definição de conexão deve ser persistente ou privada. |
True |
| POOL_CleanupTimeout | O tempo em milissegundos até o FireDAC remover as conexões que não foram usadas até o tempo POOL_ExpireTimeout. O valor padrão é 30000 ms (30 segundos). |
15000 ms 15 s |
| POOL_ExpireTimeout | O tempo em milissegundos, após o qual a conexão inativa pode ser excluída do pool e destruída. O valor padrão é 90000 ms (90 segundos). |
60000 ms 60 s |
| POOL_MaximumItems | O número máximo de conexões no Pool. Quando o aplicativo requer mais conexões, uma exceção é gerada. O valor padrão é 50. Quando se atinge o número total de conexões especificada nessa propriedade, é gerado uma exceção: |
100 |
Em geral, o FDManager mantém um pool de conexões "física" aberta, quando:
Para usar o FDManager com outros bancos de dados, verificar o link: Database Connectivity (FireDAC) #Driver Linkage
| Database | DriverID | TFDConnectionDefParams | Units |
|---|---|---|---|
| Microsoft SQL Server | MSSQL | TFDPhysMSSQLConnectionDefParams | FireDAC.Phys.MSSQLDef, FireDAC.Stan.Intf, FireDAC.Phys, FireDAC.Phys.ODBCBase, FireDAC.Phys.MSSQL |
| Oracle Server | Ora | TFDPhysOracleConnectionDefParams | FireDAC.Phys.OracleDef, FireDAC.Stan.Intf, FireDAC.Phys, FireDAC.Phys.Oracle |
| PostgreSQL | PG | TFDPhysPGConnectionDefParams | FireDAC.Phys.PGDef, FireDAC.Stan.Intf, FireDAC.Phys, FireDAC.Phys.PG; |
| MySQL Server | MySQL | TFDPhysMySQLConnectionDefParams | FireDAC.Phys.MySQLDef, FireDAC.Stan.Intf, FireDAC.Phys, FireDAC.Phys.MySQL |
| IBM DB2 Server) | DB2 | TFDPhysDB2ConnectionDefParams | FireDAC.Phys.DB2Def, FireDAC.Stan.Intf, FireDAC.Phys, FireDAC.Phys.ODBCBase, FireDAC.Phys.DB2 |
| Firebird | FB | TFDPhysFBConnectionDefParams | FireDAC.Phys.FBDef, FireDAC.Stan.Intf, FireDAC.Phys, FireDAC.Phys.IBBase, FireDAC.Phys.FB |
| InterBase | IB | TFDPhysIBConnectionDefParams | FireDAC.Phys.IBDef, FireDAC.Stan.Intf, FireDAC.Phys, FireDAC.Phys.IBBase, FireDAC.Phys.IB |
| SQLite | SQLite | TFDPhysSQLiteConnectionDefParams | FireDAC.Stan.ExprFuncs, FireDAC.Phys.SQLiteDef, FireDAC.Stan.Intf, FireDAC.Phys, FireDAC.Phys.SQLite |
| MongoDB | Mongo | TFDPhysMongoConnectionDefParams | FireDAC.Phys.MongoDBDef, FireDAC.Stan.Intf, FireDAC.Phys, FireDAC.Phys.MongoDB |
| ODBC | ODBC | TFDPhysODBCConnectionDefParams | FireDAC.Phys.ODBCDef, FireDAC.Stan.Intf, FireDAC.Phys, FireDAC.Phys.ODBCBase, FireDAC.Phys.ODBC |
Em anexo no projeto existem dois exemplos de uso de conexão com o banco de dados em ambientes multithread.
1º Exemplo, usando conexões em ambiente multithreading para desktop.
2º Exemplo, usando conexões em ambiente multithreading para servidor web com Horse.
Ambos os exemplo usam o banco de dados Firebird