Willkommen bei Entwickler-Forum.
Ergebnis 1 bis 6 von 6
  1. #1
    Aufsteiger
    Registriert seit
    23.03.2007
    Beiträge
    60

    Standard 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. #2
    Stammgast
    Registriert seit
    24.10.2011
    Beiträge
    1.246

    Standard

    Zitat Zitat von petermaennchen Beitrag anzeigen
    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

  3. #3
    Aufsteiger
    Registriert seit
    23.03.2007
    Beiträge
    60

    Standard

    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

  4. #4
    Forenheld
    Registriert seit
    26.02.2003
    Beiträge
    16.146

    Standard

    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

  5. #5
    Aufsteiger
    Registriert seit
    23.03.2007
    Beiträge
    60

    Standard

    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

  6. #6
    Stammgast
    Registriert seit
    24.10.2011
    Beiträge
    1.246

    Standard

    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

 

 

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •