Ich arbeite gerade an einer Multithread-Server-App und plane, Firedac für den Datenzugriff zu verwenden. Aus den hier bereitgestellten Dokumenten: http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Multithreading_(FireDAC) scheint es, dass auf dieselben TFDConnection
und/oder TFDQuery
nicht gleichzeitig von mehreren Threads aus zugegriffen werden sollte (stattdessen sollten diese Objekte pro Thread-Basis erstellt werden).Firedac in einer Multithread-App verwenden
Daher zentralisiert das Beispiel in der vorherigen Verknüpfung die TFDConnection
und TFDQuery
in einem TThread
Objekt. In meinem Fall habe ich jedoch keine Kontrolle über die Thread-Erstellung (die von der Serverumgebung verwaltet wird). Ich beschränke daher den Lebenszyklus von meinen TFDConnection
und TFDQuery
Objekten auf die Lebensdauer eines Verfahrens, das möglicherweise von mehreren Threads aufgerufen werden kann:
procedure TAPMFiredacTemplate.executeSQL(sql:string);
var
oConn: TFDConnection;
oQuery: TFDQuery;
begin
oConn := TFDConnection.Create(nil);
oQuery := TFDQuery.Create(nil);
try
oConn.ConnectionDefName := self.ConnectionDefinitionName;
oConn.Connected := True;
oQuery.Connection := oConn;
oQuery.Open(sql);
while not oQuery.Eof do
begin
// process query
oQuery.Next;
end;
finally
if assigned(oQuery) then
begin
oQuery.Close;
oQuery.Free;
end;
if assigned (oConn) then
begin
oConn.Connected := False;
oConn.Free;
end;
end;
Ist dieser Ansatz gültig? Wird die Performance beeinträchtigt, indem das Objekt TFDQuery
systematisch erstellt wird?
Hinweis: Um die Leistung zu verbessern, plane ich die Verwendung einer privaten gepoolten Verbindungsdefinition (die von der TFDConnection
verwendet wird). Also von meinem Verständnis, auch wenn ich die TFDConnection
befreien, wird die physikalische Verbindung nicht zerstört, sondern wieder in den Pool:
oParams := TStringList.Create;
oParams.Add('Database=localhost:c:\apm\databases\mydb.FDB');
oParams.Add('User_Name=xxxxx');
oParams.Add('Password=xxxxxx');
oParams.Add('Pooled=True');
FDManager.AddConnectionDef('Firebird_Pooled','FB',oParams);
FDManager.Active := True;
Es gibt eine Leistungseinbuße für den ersten Ansatz. Lesen Sie weiter zu [Connection Pooling] (http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Multithreading_ (FireDAC) #Connection_Pooling). Sie können dann [das Beispiel] (http://docwiki.embarcadero.com/CodeExamples/Tokyo/en/FireDAC.Pooling_Sample) überprüfen. – Victoria
Ich dachte daran, einen Verbindungspool im Voraus über den 'FDManager' zu erstellen und dann diese gepoolte Verbindung in meiner Prozedur zu verwenden (siehe Anmerkung). Also auch, wenn ich die 'TFDConnection', die physikalischen Verbindungen oder die aus dem Pool kommen, freistelle. Dies sollte die Leistung verbessern. Ich bin mir jedoch nicht sicher, was ich tun kann, um 'TFDQuery' zu optimieren. – BigONotation
Das Vorbereiten einer Abfrage kann eine andere teure Operation sein. Wenn Ihr Server Keep-Alive-Art von Verbindung unterstützt, erstellen Sie das Abfrageobjekt und bereiten Sie die Abfrage vor, wenn der Client eine Verbindung herstellt, und zerstören Sie die Abfrage, wenn die Verbindung getrennt wird. Jede Anfrage kann dann mit dem vorbereiteten Anfrageobjekt (referenziert von der Kontextklasse) bearbeitet werden. – Victoria