Entwickler-Ecke
Datenbanken - Offene Datenbankverbindungen/Fehler:zu viele offene Tabellen
jjturbo - Di 26.06.07 09:17
Titel: Offene Datenbankverbindungen/Fehler:zu viele offene Tabellen
Moin Forum,
kann man sich irgendwie anzeigen lassen, wie viele Datenbankverbindungen (m)eine Applikation offen hat?
Danke im voraus, jjturbo
BenBE - Di 26.06.07 09:32
Wenn Du auf einen MySQL-Server zugreifst, kannst Du das mit SHOW FULL PROCESSLIST machen. Für andere Datenbanken wird es da sicherlich auch Wege geben.
jjturbo - Di 26.06.07 15:05
Ich habe mal wieder ein Problem, und das nennt sich "Zu viele offene Tabellen vorhanden"
Jetzt habe ich die Stelle gefunden, wo in meinem Programm der Fehler auftritt.
Bei der aktuell verwendeten Datenmenge tritt der Fehler jedes mal exakt beim einundzwanzigsten Aufruf dieser Prozedur auf, und zwar bei "QueryBearbdaten.Active := True;"
Anbei der Quellcode der Prozedur. Sieht da jemand ein Problem?
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78:
| procedure TMyProc.BearbeitungEinfuegen(PosStr1:String;TeilNr:Integer;AnschnittWinkel:Real); var SQLText :String; Tabellenname :String; Verz :String; PosStr2 :String; PosReal :Real; Winkel :Real; XPos :Real; VersatzBohrer :Real; EffSaegeblBrLi :Real; QueryBearbdaten :TQuery; begin
QueryBearbdaten := TQuery.Create(HauptForm); QueryBearbdaten.DataSource := HauptForm.DataSourceBearbdaten;
Tabellenname := ExtractFilename(HauptForm.TableBearbdaten.TableName); Verz := ExtractFilePath(HauptForm.TableBearbdaten.TableName);
SQLText := 'SELECT * from ' + Tabellenname + ' WHERE teilnr = ' + QuotedStr(IntToStr(TeilNr)); protokoll(clgreen,'SQL: ' + SQLText);
QueryBearbdaten.SQL.Clear; QueryBearbdaten.SQL.SetText(PChar(SQLText)); QueryBearbdaten.DatabaseName := Verz; QueryBearbdaten.ExecSQL;
TRY QueryBearbdaten.Active := True; EXCEPT QueryBearbdaten.Active := false; FreeAndNil(QueryBearbdaten); protokoll(clRed,'Fehler beim Öffnen der Bearbeitungsdaten'); Exit; END;
QueryBearbdaten.First; while not QueryBearbdaten.Eof do begin
Winkel := QueryBearbdaten.FieldbyName('Winkel').AsFloat; XPos := QueryBearbdaten.FieldbyName('X').AsFloat; VersatzBohrer := DrehpunktHinterNull_Bohrer * tan(Winkel*pi/180); EffSaegeblBrLi := EffektiveSaegeblattBreite(SaegeblattBreiteZangenseitig,0,AnschnittWinkel);
PosReal := StrToFloat(PosStr1) - EffSaegeblBrLi*1000 - XPos*1000 + OffsetBohrer*1000 + VersatzBohrer*1000; PosReal := Round(PosReal/100)*100; PosStr2 := FormatFloat('00000000',PosReal);
HauptForm.TableSPSDaten.Append; HauptForm.TableSPSDaten.FieldByName('ZangenPosition').AsString := PosStr2; HauptForm.TableSPSDaten.FieldByName('Bearb').AsString := QueryBearbdaten.FieldbyName('Bearb').AsString; HauptForm.TableSPSDaten.FieldByName('TeilNr').AsInteger := TeilNr; HauptForm.TableSPSDaten.FieldByName('Länge').AsInteger := 0; HauptForm.TableSPSDaten.FieldByName('Winkel').AsFloat := Winkel; HauptForm.TableSPSDaten.FieldByName('WertSchwenkachse').AsInteger := SollWertSchwenkachseBerechnen(Winkel); HauptForm.TableSPSDaten.FieldByName('Y').AsFloat := QueryBearbdaten.FieldbyName('Y').AsFloat; HauptForm.TableSPSDaten.FieldByName('Z').AsFloat := QueryBearbdaten.FieldbyName('Z').AsFloat; QueryBearbdaten.Next;
end;
QueryBearbdaten.Close; FreeAndNil(QueryBearbdaten);
end; |
Danke im voraus, jjturbo
jjturbo - Di 26.06.07 16:50
...acho so: Verwendet werden lokale Paradox-Tabellen und die BDE
kkausp - Di 26.06.07 18:28
Ich habe es mal ein bisschen geändert. Mit freeandnil hatte ich mal Probleme. Ansonsten vermute ich das eventuell in der Schleife eine exception auftritt und die qeury nicht mehr freigeben wird.
Die subroutienen rufen keine DB mehr auf?
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76:
| procedure TMyProc.BearbeitungEinfuegen(PosStr1:String;TeilNr:Integer;AnschnittWinkel:Real); var SQLText :String; Tabellenname :String; Verz :String; PosStr2 :String; PosReal :Real; Winkel :Real; XPos :Real; VersatzBohrer :Real; EffSaegeblBrLi :Real; QueryBearbdaten :TQuery; begin
QueryBearbdaten := TQuery.Create(HauptForm); try try QueryBearbdaten.DataSource := HauptForm.DataSourceBearbdaten; Tabellenname := ExtractFilename(HauptForm.TableBearbdaten.TableName); Verz := ExtractFilePath(HauptForm.TableBearbdaten.TableName);
SQLText := 'SELECT * from ' + Tabellenname + ' WHERE teilnr = ' + QuotedStr(IntToStr(TeilNr)); protokoll(clgreen,'SQL: ' + SQLText);
QueryBearbdaten.SQL.Clear; QueryBearbdaten.SQL.SetText(PChar(SQLText)); QueryBearbdaten.DatabaseName := Verz; QueryBearbdaten.ExecSQL;
QueryBearbdaten.Active := True; QueryBearbdaten.First; while not QueryBearbdaten.Eof do begin
Winkel := QueryBearbdaten.FieldbyName('Winkel').AsFloat; XPos := QueryBearbdaten.FieldbyName('X').AsFloat; VersatzBohrer := DrehpunktHinterNull_Bohrer * tan(Winkel*pi/180); EffSaegeblBrLi := EffektiveSaegeblattBreite(SaegeblattBreiteZangenseitig,0,AnschnittWinkel);
PosReal := StrToFloat(PosStr1) - EffSaegeblBrLi*1000 - XPos*1000 + OffsetBohrer*1000 + VersatzBohrer*1000; PosReal := Round(PosReal/100)*100; PosStr2 := FormatFloat('00000000',PosReal);
HauptForm.TableSPSDaten.Append; HauptForm.TableSPSDaten.FieldByName('ZangenPosition').AsString := PosStr2; HauptForm.TableSPSDaten.FieldByName('Bearb').AsString := QueryBearbdaten.FieldbyName('Bearb').AsString; HauptForm.TableSPSDaten.FieldByName('TeilNr').AsInteger := TeilNr; HauptForm.TableSPSDaten.FieldByName('Länge').AsInteger := 0; HauptForm.TableSPSDaten.FieldByName('Winkel').AsFloat := Winkel; HauptForm.TableSPSDaten.FieldByName('WertSchwenkachse').AsInteger := SollWertSchwenkachseBerechnen(Winkel); HauptForm.TableSPSDaten.FieldByName('Y').AsFloat := QueryBearbdaten.FieldbyName('Y').AsFloat; HauptForm.TableSPSDaten.FieldByName('Z').AsFloat := QueryBearbdaten.FieldbyName('Z').AsFloat;
HauptForm.TableSPSDaten.post; QueryBearbdaten.Next;
end;
QueryBearbdaten.Close;
EXCEPT protokoll(clRed,'Fehler'); END;
finally QueryBearbdaten.free; end; end; |
raiguen - Di 26.06.07 18:54
Moin :-)
Ähm... das hier
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| QueryBearbdaten := TQuery.Create(HauptForm); QueryBearbdaten.DataSource := HauptForm.DataSourceBearbdaten;
Tabellenname := ExtractFilename(HauptForm.TableBearbdaten.TableName); Verz := ExtractFilePath(HauptForm.TableBearbdaten.TableName); SQLText := 'SELECT * from ' + Tabellenname + ' WHERE teilnr = ' + QuotedStr(IntToStr(TeilNr)); |
ist m.E. nicht unbedingt sinnvoll :roll: Ich nehme mal sehr stark an, dass sich Tabellenname und Verz nicht ändern, also quasi 'constant' sind?
Ich würde so vorgehen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42:
| ... private QueryBearbDaten: TQuery; public ....
procedure TMyProc.BearbeitungEinfuegen(PosStr1:String;TeilNr:Integer;AnschnittWinkel:Real); var SQLText :String; Tabellenname :String; Verz :String; PosStr2 :String; PosReal :Real; Winkel :Real; XPos :Real; VersatzBohrer :Real; EffSaegeblBrLi :Real; begin if not Assigned(QueryBearDaten) then begin Tabellenname := ExtractFilename(HauptForm.TableBearbdaten.TableName); Verz := ExtractFilePath(HauptForm.TableBearbdaten.TableName); QueryBearbdaten := TQuery.Create(HauptForm); QueryBearbdaten.DatabaseName := Verz;
QueryBearbdaten.DataSource := HauptForm.DataSourceBearbdaten; end;
if not QueryBearbDaten.Prepared then begin QueryBearbDaten.SQLText := 'SELECT * FROM ' + Tabellenname + ' WHERE teilnr = :TEILNR '; QueryBEarDaten.Prepare; end; QueryBearbDaten.Close; QueryBearbDaten.Params[0].AsString := IntToStr(TeilNr); QueryBearbDaten.Open; ... end; |
Die QueryBEarbDaten wird nur einmal erstellt, sofern sie noch nicht vorhanden ist und mit dem entsprechenden SQL-Statement und Parameter vorbereitet. Bei jedem weiteren Durchlauf der Procedure wird nur der PArameter übergeben... Das spart Rechnerzeit und ständiges Allozieren/Freigeben von Speicher durch den SQL-Server (auch wenn's nur die BDE-eigene Geschichte ist...)
Beim Beenden der HAuptform als Owner wird QueryBEarbDaten automatisch mit freigegeben...
jjturbo - Di 26.06.07 20:27
Danke erst mal für Eure Anregungen und Kommentare.
Ich habe damit mal ein wenig getestet, es hat aber leider nichts gebracht.
Es treten keine weiteren Exceptions auf, weitere DB-Aufrufe in den Subroutinen gibt es nicht.
Tabellenname ändert sich gelegentlich(wenn ein anderer Auftrag gefahren wird), Verz könnte sich auch ändern.
Ich sehe eigentlich nichts grundlegend falsches... :(
jjturbo - Mi 27.06.07 09:02
So, ich habe die TQuery jetz[/delphi]t mal rausgeschmissen und hole mir die benötigten Daten über TTable mit Hilfe eines Filters:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79:
| procedure TMyProc.BearbeitungsdatenFiltern(TeilNr:Integer); var TeilNrStr :String; begin
TeilNrStr := IntToSTr(TeilNr);
with HauptForm.TableBearbdaten do begin Active := false; Filter := 'TeilNr = ' + QuotedStr(TeilNrStr); Filtered := True; Active := True; end;
end;
procedure TMyProc.BearbeitungsdatenFilternAus; begin
with HauptForm.TableBearbdaten do begin Active := false; Filtered := false; Active := True; end;
end;
procedure TMyProc.BearbeitungEinfuegen(PosStr1:String;TeilNr:Integer;AnschnittWinkel:Real); var PosStr2 :String; PosReal :Real; Winkel :Real; XPos :Real; VersatzBohrer :Real; EffSaegeblBrLi :Real; begin
BearbeitungsdatenFiltern(TeilNr);
HauptForm.TableBearbdaten.First; while not HauptForm.TableBearbdaten.Eof do begin
Winkel := HauptForm.TableBearbdaten.FieldbyName('Winkel').AsFloat; XPos := HauptForm.TableBearbdaten.FieldbyName('X').AsFloat; VersatzBohrer := DrehpunktHinterNull_Bohrer * tan(Winkel*pi/180); EffSaegeblBrLi := EffektiveSaegeblattBreite(SaegeblattBreiteZangenseitig,0,AnschnittWinkel);
PosReal := StrToFloat(PosStr1) - EffSaegeblBrLi*1000 - XPos*1000 + OffsetBohrer*1000 + VersatzBohrer*1000; PosReal := Round(PosReal/100)*100; PosStr2 := FormatFloat('00000000',PosReal);
HauptForm.TableSPSDaten.Append; HauptForm.TableSPSDaten.FieldByName('ZangenPosition').AsString := PosStr2; HauptForm.TableSPSDaten.FieldByName('Bearb').AsString := HauptForm.TableBearbdaten.FieldbyName('Bearb').AsString; HauptForm.TableSPSDaten.FieldByName('TeilNr').AsInteger := TeilNr; HauptForm.TableSPSDaten.FieldByName('Länge').AsInteger := 0; HauptForm.TableSPSDaten.FieldByName('Winkel').AsFloat := Winkel; HauptForm.TableSPSDaten.FieldByName('WertSchwenkachse').AsInteger := SollWertSchwenkachseBerechnen(Winkel); HauptForm.TableSPSDaten.FieldByName('Y').AsFloat := HauptForm.TableBearbdaten.FieldbyName('Y').AsFloat; HauptForm.TableSPSDaten.FieldByName('Z').AsFloat := HauptForm.TableBearbdaten.FieldbyName('Z').AsFloat; HauptForm.TableSPSDaten.Post; HauptForm.TableBearbdaten.Next; end;
BearbeitungsdatenFilternAus;
end; |
Es werden die gleichen Daten abgefragt, der Fehler scheint aber damit behoben zu sein.
Dennoch würde mich interessieren wo der Fehler liegt.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!