MSSQL TSQLQuery Abbruch.

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Antworten
Thandor
Beiträge: 152
Registriert: Sa 30. Jan 2010, 18:17
OS, Lazarus, FPC: Windows 10 64Bit/ lazarus 2.2.0 mit FPC 3.2.2 (32Bit)
CPU-Target: 64Bit
Wohnort: Berlin

MSSQL TSQLQuery Abbruch.

Beitrag von Thandor »

Hallo,

ich führe bei einem TSQLQuery ein Select aus. Die Datenbank ist sehr groß. Nun möchte ich dem Benutzer meiner Software ein Abbruch-Button zur verfügung stellen. Jedoch bleibt das Programm bei dem Aufruf von SQLQuery.Close scheinbar hängen. Wenn ich im Select aber eine TOP xxx mitgebe läuft er durch das close durch. Ich vermute mal, das da noch irgendwas gemacht wird, worauf das close wartet.

Da der Zugriff im jeden Fall nur lesend ist, sollte doch eigentlich kein Rollback nötig sein. Was macht TSQLQuery bei close, was da so lange dauert? Wie kann ich einen sofortigen Abbruch eines Selects realisieren?

Code: Alles auswählen

procedure TForm_Execute.ProgressSQlRequest();
var i, Row, Col      : Integer;
    FieldName, Value : String;
begin
  Log.PostInfo('Execute SQL-Request...');
  with Form_Main do begin
    try
      SQLQuery.Open();
      
      while (not SQLQuery.EOF) and (not doCancel) do begin
        for i := 0 to SQLQuery.Fields.Count - 1 do begin
          //...
        end;

        Application.ProcessMessages();
        SQLQuery.Next();
      end;

      if doCancel then begin
        Log.PostInfo('Cancel SQL-Request...');
      end;
      Log.PostInfo('Close SQL-Request...');
      SQLQuery.Close();
      Log.PostInfo('SQLQuery Closed...');

    except
      on E:Exception do begin
        Log.PostError('Execute: ' + E.ToString);
        Exit();
      end;
    end;
  end;
  Log.PostInfo('Done.');
end; {ProgressSQlRequest}
Mach ich was falsch? Habe ich was vergessen?
Das SQL-Statement wird vor aufruf der obigen Methode mittes "SQLQuery.SQL.Text := SQLStatement;" gesetzt.


LG
Thandor

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 5478
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Niederösterreich
Kontaktdaten:

Re: MSSQL TSQLQuery Abbruch.

Beitrag von af0815 »

Ich finde mal nichts, was mir auffällt.
Hast du bei der Query auch als ReadOnly gekennzeichnet, damit das System aus sicher weis, das das ganze nur lesend ist. Ob eine Datenbank groß ist, ist mal egal, solange das Recordset was durch das Select gebildet wird nicht ausufert.

Eine Frage verwendest du ODBC oder die TDS Verbindung (MSSQLConnection) ?

Mit dem TOP xxx schränkst du den Bereich deutlich ein. Beinhaltet dein Select auch JOINS ?! Oder visuelle Komponeneten ?
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Thandor
Beiträge: 152
Registriert: Sa 30. Jan 2010, 18:17
OS, Lazarus, FPC: Windows 10 64Bit/ lazarus 2.2.0 mit FPC 3.2.2 (32Bit)
CPU-Target: 64Bit
Wohnort: Berlin

Re: MSSQL TSQLQuery Abbruch.

Beitrag von Thandor »

Ich benutze die Komponenten TSQLConnector, TSQLTransaction und TSQLQuary für die Verbindung.

In TSQLConnector ist als ConectorType MSSQLServer eingestellt.
In TSQLTransaction ist unter Action caNone eingestellt.
In TSQLQuary keine besonderen Einstellungen.
af0815 hat geschrieben:
Mo 21. Nov 2022, 18:33
Hast du bei der Query auch als ReadOnly gekennzeichnet
Meinst du die Eigenschaft ReadOnly von TSQLQuary? Das hatte ich mal testweise gemacht. Hat aber gefühlt keien Unterschied gemacht.
af0815 hat geschrieben:
Mo 21. Nov 2022, 18:33
Beinhaltet dein Select auch JOINS ?! Oder visuelle Komponeneten
Keine Joins und keine visuellen Komponenten. Das Select hat folgende Struktur.

select [Feld1, Feld2, ...] oder [*]
from [Tabelle]
[where ...]

Keine verweise auf andere Tabellen. Nur eine Tabelle ist involviert.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 5478
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Niederösterreich
Kontaktdaten:

Re: MSSQL TSQLQuery Abbruch.

Beitrag von af0815 »

TSQLConnector ist IMHO ODBC
TMSSQLConnection geht über der TDS- oder Microsoft Treiber (die muss man mal installieren/kopieren das es geht)

mit ODBC habe ich leider absolut keine Erfahrung. Keine Ahnung ob der vielleicht komisch auf das Close reagiert und noch schnell alles mal fetched. Ich verwende die ODBC nicht, da einiges was der MS-SQL kann, dort nicht unterstützt wird, ausserdem wird es mit ODBC meiner Erfahrung nach etwas komplizierter unter Linux. Ich arbeite unter Windows und Linux mit den TDS-Treibern. Die können auch nicht alles vom Server auflösen, waren aber besser als ODBC.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

PascalDragon
Beiträge: 623
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: MSSQL TSQLQuery Abbruch.

Beitrag von PascalDragon »

af0815 hat geschrieben:
Di 22. Nov 2022, 11:04
TSQLConnector ist IMHO ODBC
Nein, TSQLConnector ist ein dynamischer Selektor für die verschiedenen SQL Anbindungen, die in FPC existieren.
FPC Compiler Entwickler

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 5478
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Niederösterreich
Kontaktdaten:

Re: MSSQL TSQLQuery Abbruch.

Beitrag von af0815 »

PascalDragon hat geschrieben:
Di 22. Nov 2022, 21:36
af0815 hat geschrieben:
Di 22. Nov 2022, 11:04
TSQLConnector ist IMHO ODBC
Nein, TSQLConnector ist ein dynamischer Selektor für die verschiedenen SQL Anbindungen, die in FPC existieren.
Das heisst somit eine Factory für die vorhandenen SQL Anbindungen. Und woher werden dann die Treiber genommen ? Von den spezialisierten SQL Anbindungen ?
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

charlytango
Beiträge: 575
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz 2.0 fixes FPC 3.2 fixes
CPU-Target: Win 32Bit, 64bit
Wohnort: Wien

Re: MSSQL TSQLQuery Abbruch.

Beitrag von charlytango »

Falls ich das richtig behirnt habe:

Der TSQLConnector ist wie Pascaldragon sagte ein Selektor für die von FPC bereitgestellten Datenverbindungen. Über dessen ConnectorType kann ausgesucht werden welche der Datenverbindungen benutzt wird.
Erzeugt wird intern die durch den ConnectorType ausgewählte Datenverbindung (zB TMSSQLConnection)

Damit das klappt muss auch die (oder mehrere) gewünschte unit dieser Datenverbindung mit eingebunden werden. Im Falle von MSSQL eben mssqlconn

Code: Alles auswählen

uses
 ....
  //, SQLite3Conn  //SQLite3
  //,pqconnection     //PostgreSQ
  //,ibconnection     //Interbase ,Firebird
  ,mssqlconn        //MSSQL Server , Sybase
  //,oracleconnection //Oracle
  //,odbcconn         //ODBC Access
  //,mysql40conn      //different MySQL Versions as well as MariaDB
  //,mysql41conn
  //,mysql50conn
  //,mysql51conn
  //,mysql55conn
  //,mysql56conn
  //,mysql57conn
  //,mysql80conn
;
Die Namen der Standard-Zugriffs-DLLs (oder SOs) bekommt man über GetStandardLibraryName(cConnectorType);
Natürlich müssen die DLLs installiert sein damit sie benutzt werden können.
Laden und entladen der Librarys überneimmt TSQLDBLibraryLoader.

In meinem DB-Beispiel hab ich das so benutzt, funktioniert erstaunlich gut. Zwisschen mehreren Datenbank-Connektoren umschalten hab ich allerdnigs noch nicht probiert aber die Library immer auch entladen.

Was ich komisch finde ist, dass die Konstanten und Stringarrays für die Unterschiedung von Servertypen und Connectortypen (TSQLConnType, TSQLServerType, SQLConnTypesNames bzw die Variablen SQLConnType und SQLServerType ) schwer zugängig sind.
Die befinden sich offensichtlich in der Unit SQLDBToolsUnit, die wird aber beim Einbinden in der uses section nicht gefunden... grübel. Kann auch sein dass ich da auf dem falschen Dampfer bin und einfach zu blöd zum Einbinden bin.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 5478
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Niederösterreich
Kontaktdaten:

Re: MSSQL TSQLQuery Abbruch.

Beitrag von af0815 »

Ok, dann werden die ganzen Treiber so wie bisher benötigt. Und das ganze wirklich ein Selector und keine Factory. Ist vielleicht von Vorteil, wenn man breit sich aufstellt für Verbindungen. Nachdem ich da ganz spezialisiert fahre mit dem TMSSQLConnection bringt es mir aktuell nicht wirklich was. (Ausser neue Informationen)

Das hilft aber bei Thandor's Problem nicht. Und darum geht es im Thread hier.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Thandor
Beiträge: 152
Registriert: Sa 30. Jan 2010, 18:17
OS, Lazarus, FPC: Windows 10 64Bit/ lazarus 2.2.0 mit FPC 3.2.2 (32Bit)
CPU-Target: 64Bit
Wohnort: Berlin

Re: MSSQL TSQLQuery Abbruch.

Beitrag von Thandor »

Also ich komme echt nicht weiter.

Ich habe nochmal versucht durch das Close zu stepen, aber der Debuger bleibt beim betreten von Close schon stehen. Wenn ich mit Strg + Mausclik auf SQLQuery.Close gehe lande ich in der dataset.inc bei folgender Methode:

Code: Alles auswählen

procedure TDataSet.Close;

begin
  Active:=False;
end;   
Wie kann da was den Programmfluss ausbremsen? Was wird hier vor mir "versteckt"? Ich denke mal, das dass an den Selektor liegt. Aber wie wird das Close dann verarbeitet?
Ich würde ja schon gerne mal durch den richtigen Close-Code stepen und schauen, was da gemacht wird und wo es dann hängt. Aber ich kann ihn nicht finden.

[Edit] Aber TDataSet.Close wird offenbar gar nict genutzt. Ein Haltepunkt hier wird nicht ausgelöst.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 5478
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Niederösterreich
Kontaktdaten:

Re: MSSQL TSQLQuery Abbruch.

Beitrag von af0815 »

Thandor hat geschrieben:
Fr 25. Nov 2022, 10:29
Aber TDataSet.Close wird offenbar gar nict genutzt. Ein Haltepunkt hier wird nicht ausgelöst.
Das kann sein, das ein close der spezialisierten Verbindung verarbeitet wird.

Das heisst du kommst einmal bis zum Close in deinem Code.

Code: Alles auswählen

      Log.PostInfo('Close SQL-Request...');
      SQLQuery.Close();  // < -- bis hierher ??
      Log.PostInfo('SQLQuery Closed...');
Daher die Schleife wird abgebrochen.
Ändert sich was, wenn du vor dem SQLQuery.Close ein SQLQuery.Last einfügst ? Damit zwingst du auf den letzen Datensatz. Könnte man in der Schleife schon vorher machen, das man im falle von Cancel kein next macht, sondern ein Last. Damit springt man ans Ende der Daten.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Thandor
Beiträge: 152
Registriert: Sa 30. Jan 2010, 18:17
OS, Lazarus, FPC: Windows 10 64Bit/ lazarus 2.2.0 mit FPC 3.2.2 (32Bit)
CPU-Target: 64Bit
Wohnort: Berlin

Re: MSSQL TSQLQuery Abbruch.

Beitrag von Thandor »

Ja, er bleibt beim Close stehen.

Wenn ich nun ein SQLQuery.Last einfüge, so bleibt er beim Last eine Weihle stehen kommt dann aber auf eine Exception. RunError(203) -> Heap overflow

Code: Alles auswählen

    try
      SQLQuery.Open();
      SQLQuery.First();
      
      while (not SQLQuery.EOF) and (not doCancel) do begin
        for i := 0 to SQLQuery.Fields.Count - 1 do begin
          //...
        end;
        Application.ProcessMessages();
        if not doCancel then SQLQuery.Next()
        else                 SQLQuery.Last();   //<-- Last, wenn Abbruch; Hier bleibt er stehen und wirft die Exception
      end;
      
      SQLQuery.Close();
      
    except
      on E:Exception do begin
        Exit();
      end;
    end;
Ohne Last kommt keine Exception. Ich habe das mal versucht und das Abbrechen eine Nacht lang laufen lassen (In der Version vom ersten Beitrag). Am nächsten Morgen war das Programm in dem Zusatnd, wie es nach einem Abbruch sein sollte. Hat fast den Anschein, als ob das Close dennoch alle Datensätze durchakert obwohl das nicht nötig ist. :roll:

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 5478
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Niederösterreich
Kontaktdaten:

Re: MSSQL TSQLQuery Abbruch.

Beitrag von af0815 »

Ich habe es vermutet, das er vor dem Close noch den Fetch vollendet.

Jetzt musst nur noch verraten, warum du soviele Einträge brauchst. Normalerweise begrenzt man das, oder lässt es im Hintergrund laufen (oder lagert es auf den Server aus)
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Thandor
Beiträge: 152
Registriert: Sa 30. Jan 2010, 18:17
OS, Lazarus, FPC: Windows 10 64Bit/ lazarus 2.2.0 mit FPC 3.2.2 (32Bit)
CPU-Target: 64Bit
Wohnort: Berlin

Re: MSSQL TSQLQuery Abbruch.

Beitrag von Thandor »

Es handelt sich hier umm ein Programm, um eine Changelog-Datenbank zu durchsuchen.
Der Benutzer kann, dynamisch entsprechende Filter setzen.
Auch den Wert vom Parameter "TOP" kann der Benutzer frei wählen. Wenn er nix einträgt entfällt TOP für die Anfrage.

Nun kann es also sein, dass der Nutzer der Meinung ist, er wolle die Anfrage nicht begrenzen. Nun stellt er aber fest: "oh hoppla das dauert ja ziemlich lange" und möchte die Abfrage abbrechen...

Auf dem Server selber habe ich keinen Einfluss. Als Thread, ja habe ich auch schon überlegt, nur was passiert, wenn eine langwierige Abfrage abgebrochen wird und währen die noch geschlossen wird eine neue gestartet wird? Um da keine Kollisionen zu haben müsste ich pro Abfrage eine neue Threadinstanz erzeugen mit je einem eigenen TSQLQuery. Was passiert, wenn das Programm direkt nach dem Abbrechen einer langwierigen Abfrage beendet werden soll? Dann würde das Programm doch auch ewig brauchen, bis es sich ordentlich beendet.

LG
Thandor

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 5478
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Niederösterreich
Kontaktdaten:

Re: MSSQL TSQLQuery Abbruch.

Beitrag von af0815 »

Thandor hat geschrieben:
Mo 28. Nov 2022, 07:16
Nun kann es also sein, dass der Nutzer der Meinung ist, er wolle die Anfrage nicht begrenzen. Nun stellt er aber fest: "oh hoppla das dauert ja ziemlich lange" und möchte die Abfrage abbrechen...
Vielleicht ist es Effizienter, dem Benutzer vorher sagen, das es 10Mio Einträge sind und das dauern wird.

Ich habe das schon gemacht und zuerst die Anzahl der Einträge dem Benutzer mitgeteilt und das er das nicht abbrechen kann. Ansonsten war ein Top 1000 drinnen. Damit haben meine Nutzer leben können. weil mehr als 100 Einträge schaut sich keiner an, da ist es dann eher wichtig, das er die Kriterien nach die er sucht, feiner fassen kann. War am Anfang eine Diskussion, nur nachdem man ja auch alles holen konnte und halt das aussitzen muss, wurde es meiner Information nach nicht mehr wirklich oft gebraucht.
Die Frage war halt, nach was wurde damals wirklich gesucht in dem Datenhaufen. Wenn das immer wieder vorkommende Ereignisse sind, so kann man schon mal das Ganze am Server gruppieren lassen, dann sind es halt 10 Gruppen, die kann wer durchsuchen und schauen ob sein Ereignis drinnen ist. Wenn ja, dann kann er gezielt danach suchen. Es hängt also stark davon ab, wie der Nutzer was sucht. Notfalls kann man ihn ja auswählen lassen in welchen Tag, Woche oder Monat er suchen will, das schränkt auch ein, aber der Benutzer fühlt sich deswegen nicht Eingeschränkt. Wie gesagt , man muss einmal in Erfahrung bringen, was der/die Nutzer wirklich wollen und man muss im Programm nicht mit dem Holzhammer arbeiten.

Edit: Das mit dem Abbrechen der Query über eine Funktion des Treibers hatten wir schon mal im Forum hier (Ev. im englischen, ich muss aufpassen das ich da was nicht verwechsle). Das Ergebnis war IMHO, das es nicht so einfach ist und hat sich irgendwie verlaufen
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

charlytango
Beiträge: 575
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz 2.0 fixes FPC 3.2 fixes
CPU-Target: Win 32Bit, 64bit
Wohnort: Wien

Re: MSSQL TSQLQuery Abbruch.

Beitrag von charlytango »

nachdem das Problem scheinbar eines ist das auf der durch den User ausgewählten Datenmenge basiert vielleicht einiges aus meinen Erfahrungen.

Alles was af0815 meinte entspricht meinen Erfahrungen.
Bei großen Datenmengen (ohne TOP XXX) erstmal den Benutzer informieren dass es lange dauern kann, danach evtl mit dem Ergebnis einer Zählung (und damit vielleicht auch einer groben Zeitschätzung) nochmals nachfragen.

Ich habe aber auch schon die SQL-Statements die der Benutzer durch seine Auswahl generiert in der DB mitgelogged. Die haben wir nach einiger Zeit analysiert und die DB optimiert. Auch mit Redundanzen um die Abfragen schneller zu machen.
Der Transport der Ergebnisdaten ist nur mit schneller Hardware zu erreichen (Server,Client UND Netzwerk)
Genaueres Nachfragen was und wann die Benutzer brauchen hat dazu geführt dass mehr als 90% aller Abfragen nur Sekunden brauchten.

Antworten