Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Speicherüberlauf des MS SQL-Servers bei ADO-Verbindung (https://www.delphipraxis.net/143895-speicherueberlauf-des-ms-sql-servers-bei-ado-verbindung.html)

windi 25. Nov 2009 16:33

Datenbank: Microsoft SQL-Server Express • Version: 2005 • Zugriff über: ADO

Speicherüberlauf des MS SQL-Servers bei ADO-Verbindung
 
Hallo,

ich benötige dringend Hilfe bei einem Datenbankproblem mit einem Microsoft SQL-Server 2005 Express Edition. Ein von mir entwickeltes Delphi-Programm greift per ADOConnection + ADOQuery auf den SQL-Server zu. Das funktioniert bei Programmneustart auch wunderbar. Das Programm läuft ca. 1 1/2 bis 2 Wochen ohne Probleme, dann irgendwann bekomme ich von der ADOQuery-Komponente beim Ausführen einer Select-Abfrage die Fehlermeldung "Für diesen Vorgang ist nicht genügend Speicher verfügbar" Fehlercode: 1240640. Laut dem Taskmanager hat zu diesem Zeitpunkt die sqlsvr.exe die für den Server maximal zu verwendende Arbeitsspeichergröße erreicht. In Zahlen: ich habe im Microsoft SQL Server Managment Studio einen maximalen Serverarbeitsspeicher von 1GB eingestellt, der Arbeitspeicherverbrauch der sqlsvr.exe liegt im um ein paar Byte darunter.
Eine Suche nach dem Fehlercode bzw. der Fehlermeldung war bis jetzt wenig von Erfolg gekrönt. Ich bin echt langsam am verzweifeln, weil ich nicht jede Woche den Rechner neu starten kann. Hatte jemand schon mal ein ähnliches Problem und könnte mir in irgendeiner Form einen Tipp oder Ratschlag geben wie ich dem Grund des Ganzen auf die Spur kommen kann? Unser Kunde dreht mir langsam den Hals um, wenn ich dafür nich bald eine Lösung finde. :-(

lg
windi

omata 25. Nov 2009 22:14

Re: Speicherüberlauf des MS SQL-Servers bei ADO-Verbindung
 
Hast du dein Programm mal auf Speicherlecks kontrolliert?

Wenn deine Anwendung 2 Wochen läuft, solltest du sicherstellen, dass dort keine Speicherlecks entstehen. Binde doch einfach mal den FastMM-Speichermanager ein und aktiviere auch das Logfile, dann kannst du, nach einer gewissen Laufzeit, vielleicht schon mehr dazu sagen. Denn vielleicht liegt es nicht an MSSQL sondern eben doch an deinem Programm.

Falls du das schon alles durchgeführt hast, entschuldige bitte mein Kommentar.

SirThornberry 26. Nov 2009 07:14

Re: Speicherüberlauf des MS SQL-Servers bei ADO-Verbindung
 
als kurzfristige Notlösung würde mir nur einfallen den Dienst in einem gewissen Interval neu zu starten.
Wenn du dein eigenes Programm beendest, bleibt dann der Speicherverbrauch des SQL-Servers weiterhin so hoch? Wenn nicht, speichert der Server eventuell während der Zeit der Verbindung Daten zwischen und ein einfaches Trennen der Verbindung vom Programm zur Datenbank bringt die Lösung.

windi 26. Nov 2009 08:19

Re: Speicherüberlauf des MS SQL-Servers bei ADO-Verbindung
 
Zitat:

Hast du dein Programm mal auf Speicherlecks kontrolliert?
Ja das habe ich. Mein Programm bleibt konstant über die 2 Wochen bei ca. 15MB Arbeitsspeicherverbrauch. Hab auch mal EurekaLog eingebunden und mitlaufen lassen. Hat keine Speicherlecks gefunden. Es ist ja auch der SQL-Server, dessen Speicher konstant bei Zugriffen hochläuft. Laut Hilfe muss das aber so sein. Der Server verwaltet wohl intern den verwendbaren Arbeitspeicher.

Zitat:

Wenn du dein eigenes Programm beendest, bleibt dann der Speicherverbrauch des SQL-Servers weiterhin so hoch?
Ja. Ein Aufräumen des allokierten Arbeitsspeichers erfolgt vom SQL-Server anscheinend nicht.

Zitat:

als kurzfristige Notlösung würde mir nur einfallen den Dienst in einem gewissen Interval neu zu starten.
Habe ich bis jetzt noch nicht probiert und mich davor gescheut, weil auf die Datenbank auch noch eine andere Applikation zugreift.

In einem Forum habe ich noch gelesen, dass es eventuell am verwendeten ADO-Treiber liegen kann. Derzeit verwende ich den "Microsoft OLE DB Provider for SQL Server"-Treiber. Mit dem bei der Installation vom MS SQL-Server 2005 zusätzlich installierten "SQL Server Native Client"-Treiber hatte ich Probleme eine Verbindung zur Datenbank aufbauen zu können. Hatte eventuell jemand schon mal mit dem Treiber ein Problem??

nahpets 26. Nov 2009 08:43

Re: Speicherüberlauf des MS SQL-Servers bei ADO-Verbindung
 
Hallo,

wie greift Dein Programm auf den Server zu?

Beim Programmstart die Verbindung aufbauen und beim Programmende wieder abbauen.

Oder:

Bei Bedarf wird die Verbindung aufgebaut und "baldmöglichst" wieder geschlossen.

Egal welchen Weg Du nimmst, versuche es mal mit dem Anderen.

Bei einem Programm, das noch auf 'nen SQL-Server 2000 zugreift, hatte ich ein ähnliches Problem, dies konnte ich durch "bedarfsgesteuertes" Öffnen und Schließen der Verbindungen reduzieren und per Taskplaner des Nachts durchgeführte Neustarts des Serverdienstes auf ein erträgliches Maß reduzieren. Zugegeben: Keine elegante Lösung.

Gibt es an den Wochenenden ein Zeitfenster, in dem Du den Dienst "gefahrlos" neustarten kannst: Sprich: Gibt es Zeiten, in denen keine Zugriffe auf den Datenbankserver erfolgen? Dein Programm muss dann allerdings damit zurecht kommen und die Verbindung neu aufbauen. Oder: Den Dienst aus Deinem Programm heraus neustarten, wenn sichergestellt ist, dass zu diesem Zeitpunkt kein anderes Programm auf die Datenbank zugreifen muss. Ja: auch das sind nur Krücken und keine wirklichen Problemlösungen.

hoika 26. Nov 2009 08:46

Re: Speicherüberlauf des MS SQL-Servers bei ADO-Verbindung
 
Hallo,

lasse dir dch den Connection-String zusammenbauen.

Dazu eine leere Text-Datei conn.udl anlegen (Ebdung ist wichtig.
Doppelklick drauf, die benötigten Daten (Provider, DB) einstellen,
Verbindung testen.

Mit OK raus.

Die Datei mit dem Editor öffnen und die Connection-String kopieren.

Der DB-Pfad / Alias ... kann ja variabler gemacht werden (%s + Format)


Heiko

windi 26. Nov 2009 09:02

Re: Speicherüberlauf des MS SQL-Servers bei ADO-Verbindung
 
Zitat:

Beim Programmstart die Verbindung aufbauen und beim Programmende wieder abbauen.
Genauso ist es implementiert. Eine Verbindung nur bei Bedarf aufbauen möchte ich nicht, in die Datenbank pro Sekunde ca. 1-7 Datensätze geschrieben werden müssen. Aller 20 Sekunden wird eine Select-Abfrage ausgeführt. Hintergrund ist die Aufzeichnung von Betriebsdaten einer Fertigungsanlage. Ich habe das Programm schon dahingehend erweitert, dass bei Fehlern die durch eine Datenbankabfrage entstehen die Verbindung zur Datenbank getrennt und anschließend neu aufgebaut wird. Leider ist das nicht wirklich hilfreich, da danach die ADOQuery Speicherzugriffsverletzungen meldet: "Zugriffsverletzung bei Adresse 7C9118D0 in Modul 'ntdll.dll'". Das Einzige was kurzzeitig hilft ist das Programm komplett zu beenden und anschließend neu zu starten.

hoika 26. Nov 2009 09:10

Re: Speicherüberlauf des MS SQL-Servers bei ADO-Verbindung
 
Hallo,

dann ist doch etwas faul.
Wie schließt die die Verbindung ?

Was passiert mit den angehängten Queries ?
Beendest du die auch (Free, (Re)Create ? )

Ich würde mal den Native Client per meinem UDL-Thread anbinden.


Heiko

nahpets 26. Nov 2009 09:14

Re: Speicherüberlauf des MS SQL-Servers bei ADO-Verbindung
 
Hallo,

das heißt schlicht und einfach: Dein Programm und die Datenbank müssen dauerhaft stabil laufen, da ist dann nix mit irgendwelchen Krücken.

Momentan habe ich leider keine Idee, wie Du das Problem wegbekommen könntest.

Gibt es hier eventuell einen Ansatz? http://entwickler-forum.de/showthread.php?t=58388

windi 26. Nov 2009 15:44

Re: Speicherüberlauf des MS SQL-Servers bei ADO-Verbindung
 
Die Datenbankverbindung wird über folgende Funktion geöffnet:
Delphi-Quellcode:
function TADODatabase.OpenDatabase: Boolean;
 begin
  Result := True;
  try
   ADOConnection.Open;
   if (Assigned(OnDBConnection)) then
    OnDBConnection(csCONNECTED);
  except
   on E: Exception do
    begin
     Result := False;
     ShowErrorMessage('Fehler beim Verbindungsaufbau mit "' + ConnectionString + '"! Grund: ' + E.Message);
    end;
  end;
 end;
... und wieder geschlossen:
Delphi-Quellcode:
function TADODatabase.CloseDatabase: Boolean;
 begin
  Result := True;
  try
   if (ADOQuery.Active) then
    ADOQuery.Active := False;
   ADOConnection.Close;
   if (Assigned(OnDBConnection)) then
    OnDBConnection(csDISCONNECTED);
  except
   on E: Exception do
    begin
     Result := False;
     ShowErrorMessage('Fehler beim Verbindungsabbau mit der Datenbank! Grund: ' + E.Message);
    end;
  end;
 end;
Eine Abfrage erfolgt im Programm über:
Delphi-Quellcode:
try
  FBDE_DB.DoSelectQuery('SELECT * FROM [dbo].[PQ25Parts_T] WHERE [TeileID]=' + IntToStr(FLastReadedMessage.TeileID));

  // ... mach irgendwas damit ...

finally
  FBDE_DB.CloseQuery;
end;
Die Funktion DoSelectQuery sieht so aus:
Delphi-Quellcode:
function TADODatabase.DoSelectQuery(Query: String): Boolean;
var StartTime: Double;
 begin
  if (ADOConnection.Connected) then
   begin
    StartTime := Now;
    try
     ADOQuery.SQL.Clear;
     ADOQuery.SQL.Add(Query);
     ADOQuery.Open;
     ADOQuery.First;
     Result := True;
    except
     on E: Exception do
      begin
       ShowErrorMessage('SQL Fehler in: "' + Query + '" auf ' + ServerName
                        + ' Grund: ' + IntToStr(E.HelpContext) + ' "' + E.Message + '"');      
       Result := False;
      end;
    end;
    if (FUseQueryActivityTimer) then
     FQueryActivity.NewQueryExecution(Query, Now - StartTime);
   end
  else
   Result := False;
 end;
Die Funktion CloseQuery sieht folgendermaßen aus:
Delphi-Quellcode:
procedure TADODatabase.CloseQuery;
 begin
  if (ADOQuery.Active) then
   ADOQuery.Close;
 end;
Die Funktionen DoSelectQuery und CloseQuery sind in einem Datenmodul angelegt, welches eine TADOConnection- und eine TADOQuery-Komponente enthält.

Was ist der Vorteil, wenn ich einen UDL-Thread verwende bzw. wie geht sowas? Ich verwende derzeit einen Arbeitsthread, der neue Meldungen von der Anlage entgegennimmt und entsprechend Querys an die Datenbank sendet. Die Vorgehensweise verwende ich so nun schon im vierten Projekt mit unterschiedlichsten Datenbanken. Leider hatte ich es bis jetzt noch nie mit derartigen Problemen zu kämpfen (aber auch noch nie mit solchen Datenmengen). :-(


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:22 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz