Announcement

Collapse
No announcement yet.

Absturz beim Datenimport

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Absturz beim Datenimport

    Guten Morgen,

    ich bräuchte mal Hilfe bei einem Problem mit einer Firebird- Datenbank

    Basics:
    Firebird V. Firebird-2.5.4.26856_0_Win32
    Win7 und Citrix als Server
    Installiert als Classic Server

    Komponenten ZEOS 7.1.4 stable
    ZConnect
    ZQuery
    SQLMonitor

    Verfügbares RAM 4GB je Instanz

    Zugriff über native Treiber firebirdd-2.5

    Beim Import kommt es ohne ersichtlichen Grund zum Absturz des Programms. Möglich das zu viele Transaktionen offen sind?

    Hier ein Auszug aus dem Protokoll an der Stelle des Absturzes. Habt Ihr eine Idee was der Grund sein könnte?
    Speicherleaks möchte ich eigentlich eher ausschließen.

    Code:
    2016-12-15 09:32:18 cat: Execute prepared, proto: firebirdd-2.5, msg: Statement 260102
    2016-12-15 09:32:18 cat: Bind prepared, proto: firebirdd-2.5, msg: Statement 3124 : 19,01.12.2016,14.12.2016,
    2016-12-15 09:32:18 cat: Execute prepared, proto: firebirdd-2.5, msg: Statement 3124
    2016-12-15 09:32:18 cat: Bind prepared, proto: firebirdd-2.5, msg: Statement 3123 : 19,01.12.2016,14.12.2016,
    2016-12-15 09:32:18 cat: Execute prepared, proto: firebirdd-2.5, msg: Statement 3123
    2016-12-15 09:32:18 cat: Bind prepared, proto: firebirdd-2.5, msg: Statement 3514 : 264,14.12.2016,14.12.2016,
    2016-12-15 09:32:18 cat: Execute prepared, proto: firebirdd-2.5, msg: Statement 3514
    2016-12-15 09:32:18 cat: Prepare, proto: firebirdd-2.5, msg: Statement 260103 : Select Firma, Filiale, Abteilung from Kostentraeger where ID = ?
    2016-12-15 09:32:18 cat: Bind prepared, proto: firebirdd-2.5, msg: Statement 260103 : 0,
    2016-12-15 09:32:18 cat: Execute prepared, proto: firebirdd-2.5, msg: Statement 260103
    2016-12-15 09:32:18 cat: Prepare, proto: firebirdd-2.5, msg: Statement 260104 : Select KT.Bezeichnung, FMA.Bezeichnung, KS.Bezeichnung from Kostentraeger KT left join Firma FMA on FMA.ID = KT.Firma left join Kostentraeger_gruppen KS on KS.ID = KT.GruppenID where KT.ID = ?
    2016-12-15 09:32:18 cat: Bind prepared, proto: firebirdd-2.5, msg: Statement 260104 : 0,
    2016-12-15 09:32:18 cat: Execute prepared, proto: firebirdd-2.5, msg: Statement 260104
    2016-12-15 09:32:18 cat: Prepare, proto: firebirdd-2.5, msg: Statement 260105 : Select Firma, Filiale, Abteilung from Kostentraeger where ID = ?
    2016-12-15 09:32:18 cat: Bind prepared, proto: firebirdd-2.5, msg: Statement 260105 : 0,
    2016-12-15 09:32:18 cat: Execute prepared, proto: firebirdd-2.5, msg: Statement 260105
    2016-12-15 09:32:18 cat: Prepare, proto: firebirdd-2.5, msg: Statement 260106 : Select KT.Bezeichnung, FMA.Bezeichnung, KS.Bezeichnung from Kostentraeger KT left join Firma FMA on FMA.ID = KT.Firma left join Kostentraeger_gruppen KS on KS.ID = KT.GruppenID where KT.ID = ?
    2016-12-15 09:32:18 cat: Bind prepared, proto: firebirdd-2.5, msg: Statement 260106 : 0,
    2016-12-15 09:32:18 cat: Execute prepared, proto: firebirdd-2.5, msg: Statement 260106
    2016-12-15 09:32:18 cat: Execute prepared, proto: firebirdd-2.5, msg: Statement 766
    Vielen Dank für eure Mühen!

    Gruesse

    Peter

  • #2
    Originally posted by petermaennchen View Post
    Vielen Dank für eure Mühen!
    Da nicht für, ich kann anhand des Logs nichts erkennen. Insofern entstehen auch keine Mühen.
    Wie wäre es mit Programmcode?
    Gruß, defo

    Comment


    • #3
      Hallo Defo,

      das Programm ist gekapselt in eine globale Fehlerroutine.
      Leider wird nichts geschrieben, der Fehler scheint also extern aufzutreten?

      Code:
        public
          { Public declarations }
           procedure GlobalExceptionHandler(Sender: TObject; E: Exception);
      
        end;
      Code:
      procedure TFMain.GlobalExceptionHandler(Sender: TObject; E: Exception);
      var f : Textfile;
          s : String;
      begin
        assignfile(f,userpfad+'\errors.txt');
        s := e.message;
        if not fileexists(userpfad+'\errors.txt') then
          rewrite(f)
        else
          append(f);
        if Neustart then
        begin
          if (e is eZSQLException) then
          begin
            if (pos('xnet://global', e.message) > 0) and  (pos('Error Code: -902',e.message) > 0) then
            begin
              writeln(f,datetimetostr(now));
              writeln(f,'Fehlermeldung      : '+s);
              writeln(f,'Bearbeitungsfenster: '+aktfenster);
              writeln(f,'aktueller Anwender : '+inttostr(Aktuser));
              writeln(f,'');
              flush(f);
              closefile(f);
              showmessage('Firebird Server nicht aktiv.'+#13+'Programm wird beendet');
              application.terminate;
            end;
          end;
          writeln(f,FData.ZConnect1.Database);
          writeln(f,FData.ZConnect1.LibraryLocation);
        end;
        writeln(f,datetimetostr(now));
        writeln(f,'Fehlermeldung      : '+s);
        writeln(f,'Bearbeitungsfenster: '+aktfenster);
        writeln(f,'aktueller Anwender : '+inttostr(Aktuser));
        writeln(f,'');
        flush(f);
        closefile(f);
      end;
      Gruesse

      Peter

      Comment


      • #4
        Es wird wohl eher der Programmcode vom schreben in die DB interessant sein.......
        Das zeigt nur, dass keine Exception geschmissen wurde oder diese schon vorher gefangen wurde
        Christian

        Comment


        • #5
          OK,

          ich versuche das mal kurz zu fassen:

          vorher wird die Textdatei in eine Stringlist kopiert und nach Fehlern durchsucht und ev. bereinigt.
          Was zu tun ist, also wie die Felder zu interpretieren sind, steht in einer anderen Liste.

          Step 1
          Tabelle öffnen
          14 : begin
          if ZQStempel.state = dsinactive then
          ZQStempel.open;
          if (ZQStempel.state <> dsedit) and (ZQStempel.state <> dsinsert) then
          begin
          ZQStempel.append;
          Jahr := 0;
          Monat := 0;
          Tag := 0;
          Stunde := 0;
          Minute := 0;
          end;
          end;
          Step 2
          Daten eintragen

          14 : begin
          if lowercase(ZQStempel.fields[Feld].fieldName) = 'mandant' then
          //suchen der MandantenID anhand der Nummer
          begin
          q := TZReadOnlyQuery.Create(NIL);
          q.Connection := FData.ZConnect1;
          q.SQL.Add('Select ID from Mandant where Nr = :Man');
          q.Params[0].AsInteger := strtoint(HSL[0]);
          q.Open;
          if q.RecordCount = 1 then
          Aktmandant := q.Fields[0].AsInteger;
          q.Close;
          q.Free;
          end
          else
          if lowercase(ZQStempel.fields[Feld].fieldName) = 'firma' then
          //Suchen der FirmenID anhand der Nummer
          begin
          q := TZReadOnlyQuery.Create(NIL);
          q.Connection := FData.ZConnect1;
          q.SQL.Add('Select ID from Firma where (Mandant = :Man) and (Nr = :FMA)');
          q.Params[0].AsInteger := aktMandant;
          q.Params[1].AsInteger := strtoint(HSL[0]);
          q.Open;
          if q.RecordCount = 1 then
          AktFirma := q.Fields[0].AsInteger;
          q.Close;
          q.Free;
          end
          else
          if (lowercase(ZQStempel.fields[Feld].fieldName) = 'filiale') and (HSL[0] <> '-1') then
          //Suchen der FilialID anhand der Nummer
          begin
          q := TZReadOnlyQuery.Create(NIL);
          q.Connection := FData.ZConnect1;
          q.SQL.Add('Select ID from Filiale where (Firma = :Fma) and (Nr = :Fil)');
          q.Params[0].AsInteger := aktFirma;
          q.Params[1].AsInteger := strtoint(HSL[0]);
          q.Open;
          if q.RecordCount = 1 then
          AktFiliale := q.Fields[0].AsInteger;
          q.Close;
          q.Free;
          end
          else if (lowercase(ZQStempel.fields[Feld].fieldName) = 'filiale') and (HSL[0] = '-1') then
          //Keine Filiale
          AktFiliale := -1
          else
          if lowercase(ZQStempel.fields[Feld].fieldName) = 'pin' then
          //Leerstellen entfernen
          begin
          while copy(HSL[0],1,1) = ' ' do
          HSL[0] := copy(HSL[0],2,5);
          end
          else if (ZQImportdefZielfeld.asString) = '' then
          //Datum
          begin
          if (pos('Jahr',ZQImportdefQuellfeld.asString) > 0) then
          Jahr := strtoint(HSL[0])
          else
          if (pos('Monat',ZQImportdefQuellfeld.asString) > 0) then
          Monat := strtoint(HSL[0])
          else
          if (pos('Tag',ZQImportdefQuellfeld.asString) > 0) then
          begin
          Tag := strtoint(HSL[0]);
          ZQStempelDatum.asfloat := encodedate(Jahr,Monat,Tag);
          Jahr := 0;
          Monat := 0;
          Tag := 0;
          end
          else
          if (pos('Stunde',ZQImportdefQuellfeld.asString) > 0) then
          //Zeit
          Stunde := strtoint(HSL[0])
          else
          if (pos('Minute',ZQImportdefQuellfeld.asString) > 0) then
          begin
          Minute := strtoint(HSL[0]);
          ZQStempelZeit.asfloat := encodetime(Stunde,Minute,0,0);
          Stunde := 0;
          Minute := 0;
          end;
          end;
          if ZQImportdefZielfeld.asString <> '' then
          //hier die restlichen Inhalte
          begin
          if ZQStempel.fields[Feld].DataType = ftDate then
          ZQStempel.fields[Feld].asfloat := Date2shortSysdate(HSL[0])
          else if ZQStempel.fields[Feld].DataType = ftTime then
          ZQStempel.fields[Feld].asdatetime := entferneSekunden(strtotime(HSL[0]))
          else if ZQStempel.fields[Feld].DataType = ftString then
          ZQStempel.fields[Feld].AsString := AnsitoUTF8(HSL[0])
          else
          begin
          ZQStempel.fields[Feld].asstring := HSL[0];
          if lowercase(ZQStempel.fields[Feld].fieldName) = 'bart' then
          ZQStempel.FieldByNAme('OrigBart').asstring := HSL[0];
          end;
          end;
          end;
          Wurden die Teile des Datensatzes interpretiert, dann speichern

          14 : if ZQStempel.modified then
          begin
          //Falls keine Daten hierzu übermittelt werden (ZKTerm classic oder Fremddaten)
          if (ZQStempelMandant.asInteger = -1) or (ZQStempelMandant.asstring = '') then
          ZQStempelMandant.asInteger := AktMandant;
          if (ZQStempelFirma.asInteger = -1) or (ZQStempelFirma.asstring = '') then
          ZQStempelFirma.asInteger := AktFirma;
          if (ZQStempelFiliale.asInteger = -1) or (ZQStempelFiliale.asstring = '') then
          ZQStempelFiliale.asInteger := AktFiliale;
          ZQStempelOriginal.asstring := Original;
          q := TZReadOnlyQuery.Create(NIL);
          q.Connection := FData.ZConnect1;
          //Dopplungen vermeiden
          q.sql.add('Select Mandant, Firma, Filiale, PIN, Datum, Zeit, Bart '+
          'from Stempelung where (Mandant = :M) and (Firma = :FMA) and (Filiale = :FIL) and '+
          '(PIN = :PIN) and (Datum = :d1) and (Zeit = :Z1)');
          q.params[0].value := ZQStempelMandant.value;
          q.params[1].value := ZQStempelFirma.value;
          q.params[2].value := ZQStempelFiliale.value;
          q.params[3].value := ZQStempelPIN.value;
          q.params[4].value := ZQStempelDatum.value;
          q.params[5].value := ZQStempelZeit.value;
          q.open;
          if q.recordcount = 0 then
          ZQStempel.post
          else
          begin
          if odd(q.fieldByName('bart').asInteger) and (ZQStempel.fieldByName('bart').asInteger = q.fieldByName('bart').asInteger + 1) then
          ZQStempel.cancel
          else if not odd(q.fieldByName('bart').asInteger) and (ZQStempel.fieldByName('bart').asInteger = q.fieldByName('bart').asInteger - 1) then
          ZQStempel.cancel
          else if (ZQStempel.fieldByName('bart').asInteger = q.fieldByName('bart').asInteger) then
          ZQStempel.cancel;
          end;
          q.close;
          q.free;
          end;
          Das war's im Groben
          Mein Gewurschtel davor mit dem Interpretieren und Zusammenbauen der Stringlisten wäre hier zu komplex.
          Lt. Protokoll wird ja auch erst später ein Fehler generiert.

          Dummerweise kann ich mit gleichen Daten auf meinem PC nix feststellen. Daher vermute ich ein Problem mit Citrix.

          Gruesse

          Peter

          Comment


          • #6
            Ich kann da nichts feststellen (außer dass es schlecht formatiert ist und das Lesen nicht grad erleichtert).
            Warum soll es gerade an Citrix liegen?
            Und wenn es an Citrix liegt, dann vermutllich nicht an irgendeinem DB Code, der wenig mit der "Laufzeitumgebung" zu tun hat.
            Mein Verdacht wäre dann die (einzige?) Stelle, wo der Code mit dem "System" in Kontakt kommt, beim Schreiben des Logs.
            Hier könnte es Zugriffs-, Rechteprobleme o.ä. geben.

            Wenn das der Fall ist, würde es vielleicht auch ganz gut zum Absturzbild passen, Fehler in der Fehlerbehandlung.

            Da Variablen wie "Neustart" unbekannt sind, ist der Blick auf die Codeteile auch nicht hinreichend und die Fehlerbehandlung, Dateizugriffsproblematik nur einer von mehreren Ansatzpunkten.

            "Zu viele Transaktionen"
            Ich sehe keine Transaktionen im Code, genauer keine Transaktionsbehandlung.
            Der Code sieht so aus, als ob explizit gar nichts gemacht wird, in dem Fall würde ich tippen, dass jedes einzelne Post eine implizit eine Transaktion ist und damit vollkommen unproblematisch im Sinne der Systemlast auf der DB.
            Das gilt allerdings genau nur dann, wenn die Zwischenabfragen nicht auf der Tabelle laufen, in die auch geschrieben wird. Das ist m.E. nicht richtig ersichtlich bzw. mir zu anstrengend, das durchzugehen.
            Gruß, defo

            Comment

            Working...
            X