Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Mehrere DB-Verbindungen aus Dienst überfordern Firebird ?! (https://www.delphipraxis.net/130258-mehrere-db-verbindungen-aus-dienst-ueberfordern-firebird.html)

DataCool 5. Mär 2009 16:41

Datenbank: Firebird • Version: 1.0.0.796 • Zugriff über: BDE

Mehrere DB-Verbindungen aus Dienst überfordern Firebird ?!
 
Hi Leute,

ich habe 2 Firebird Datenbanken die ich aus einem Dienst herraus aus seperaten Threads anspreche.
Ein Thread importiert Daten aus einer anderen Datei und schreibt diese in "DB 2",
dabei werden Event gesteuert auch bei jedem "Insert, Update u. Delete" Daten in DB 1 geschrieben.
einer Anderer liesst Daten aus der "DB 1" und syncronisiert diese übers Inet mit einem Server.
Der Dienst hat die Berechtigung zur Interaktion mit dem Desktop und verbindet sich via BDE zur Datenbank.
Jeder Thread hat seine eigene DB-Verbindung, welche Dynamisch erzeugt und freigegeben wird !

Jetzt gibt es noch das GUI-Interface mit dem die Kunden auf der Datenbank(DB 1) arbeiten,
manchmal kommt es jetzt vor das die Kunden keine Änderungen an den Datensätzen mehr vornehmen können.
So wie's scheint bekommt die Query keine ErrorMessage nur die Daten bleiben unverändert.
Konnte das ganze bei mir noch nicht reproduzieren, aber Kunden die dieses Problem haben konnten mir keine Fehlermeldung nennen.

Ein Neustart des Rechners bringt wie so oft Abhilfe.

Hat irgentjemand eine Ahnung warum die Datenbank in eine Art "Locked" Zustand übergeht und der Dienst dabei scheinbar noch schreiben kann ?! Kann es an den Threads liegen ? An den mehrfachen DB Verbindungen die teilweise auf gleichen Tables Daten ändern ?
Oder ist das Problem bei der BDE zu suchen ? Den Diwnst könnte ich auf direkten Zugriff umstellen; das GUI-Interface nicht ohne weiteres.

Bin für jeden Tipp dankbar,

Greetz Data

hoika 5. Mär 2009 17:03

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
Hallo,

1. BDE ist AFAIK nicht threadfest
was ist pro Thread an DB-Komponenten definiert ?
2. mind. auf FB 1.5 umsteigen.




Heiko

mkinzler 5. Mär 2009 17:28

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
Besser noch FB 2.5, da kann man von er einen DB Abfragen auch die andere absetzen

DataCool 5. Mär 2009 17:42

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
Hi Leute,

wenn das Umstellen mal eben so erledigt wäre, hätte ich das schon lange erledigt ;-)

Das ganze läuft in über 100 Standorten ...

Die Threads haben jeweils ein TDatabase und mehere TQuerys.

Greetz Data

mkinzler 5. Mär 2009 18:38

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
Um so wichtiger ist es eine Alternative zur BDE zu implementieren.Die Migration von FB 1.x auf FB 2.x geht meist schmerzfrei.

DataCool 5. Mär 2009 20:24

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
@mkinzler:

Stimme ich Dir absolut voll zu, das steht auch ganz oben auf meine ToDo-Liste für V2 meines Programms.

Allerdings brauche im Moment eine Quick & Dirty Lösung des Problems,
d.h. würde es helfen das ganze aus den Threads auszulagern und innerhalb eines Timers im Dienst auszuführen ?

Greetz Data

hoika 5. Mär 2009 20:53

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
Hallo,

die Threads brauchen auch je ein TSession.
Such mal im Netz nach BDE multithread.

Heiko

DataCool 6. Mär 2009 14:12

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
@Hoika:
^^^^ Gesagt getan,

werde jetzt in meine Klasse die die Datenbankverbindung kapselt für jede(s) Verbindung/TDatabase eine eigene Session erzeugen.
Wenn ich das richtig verstanden hae sollte das mein Problem bis zur Umstellung erstmal beheben, richtig ?

Greetz Data

neo4a 6. Mär 2009 14:44

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
Ja, das hilft möglicherweise.

Deine Darstellung aus dem Eröffungs-Post deutet für mich auf ein Transaktions- Deathlock- Problem hin (zwei Verbindungen ändern Datensätze gleichzeitig). Das kann durchaus durch After/Before/Trigger ausgelöst sein und damit Änderungen auch in dritten Tabellen verursachen (bspw. Log- oder Summary-Tabellen). Dies wäre dann allerdings ein DB-Design- Problem, das Du auch nicht mit Sessions löst.

Prüfe, ob Trigger oder Stored Procedures involviert sind, die bei Datenänderung ihrerseits Daten ändern. Falls das nicht der Fall ist, dann war's tatsächlich nur die BDE mit unklarem Transaktionsverhalten.

--
Andreas

hoika 6. Mär 2009 14:52

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
Hallo,

Einspruch ;)
Unklares Transaktons-Verhalten der BDE ?
Damit hatte ich noch nie Probleme.

Aber trotzdem noch eine Frage zu Transaktionen.
Steuerst du die Transaktionen selber (DB.StartTransaction / DB.Commit),
oder überlässt du das der BDE ?


Heiko

mkinzler 6. Mär 2009 14:56

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
Die BDE kann m.W. aber nur SoftCommits ( gleiches Problem wie bei Zeos)

DataCool 6. Mär 2009 15:08

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
@neo4All:

Es sind definitiv keine Trigger oder SP's involviert !!!

@hoika:
Die BDE Einstellungen stehen auf "Shared No autocimmit".
StartTransaction, Commit, Rollback verwende ich nur expilzit innerhalb der User-App bei längeren Operationen.

Um etwas Licht ins dunkle zu bringen:

Ich habe eine Datenbank, wo die "wirklichen" Daten der Applikation enthalten sind,
zusätzlich gibt es in dieser DB noch eine Tabelle "SQL_TRANSFER" in der ich
jedes Änderungsstatement(Insert, Update, Delete) speichere(zur Syncronisierung mit einer DB im RZ).
Normalegröße: 2MB - 40 MB.

Dann gibt es eine 2te Datenbank die Daten aus einem Kassensystem via Exportfile importiert,
da steht dann jeder "Sch.." Bon, Artikel und Tastendruck eines Kellners drin.
Der Import läuft innerhalb eines Dienstes(innerhalb eines Timers, wenn Exportdatei vorhanden).
Der Dienst hat eine Verbindung zu DB1 und zu DB2,
um in DB2 die Kassendaten zu schreiben und in DB1 die "SQLs zu locken".

Ein Thread innerhalb des Dienstes syncronisiert dann via Internet die SQLS mit einem Server im RZ.


Konflikte könnte es geben:

- Wenn die Exportdatei importiert wird und eine User die GUI App nutzt, schreiben beide(Dienst und App)
in "SQL_Transfer"(App nur schreiben und Dienst schreiben und Lesen)

- Wenn der Dienst fertig mit import ist schreibt er 1 SQL zur Änderung in in DB1(Update auf den Umsatz eines Tages),
theoretisch könnte ein User mit der Gui auch gerade diesen Tag bearbeiten.

Ich weiß eine sehr seltsame Konstruktion, aber das System ist seit Jahren gewachsen.
Früher hatte ich die SQL-Syncronisation auch einfach via File-Transfer an den Server gemacht(komplette DB) und
der Server hat das ganze dann mit BatchMove gemerged.
Das geht jetzt aber nicht mehr, weil die Kassendaten auch in RZ sollen und da reden wir von Daten zwischen 200 MB bis 1 GB.
Deshalb die Idee mit dem SQL locken und transferieren, aber seitdem gibt es halt die bEschriebenen Probleme aber auch nur sporadisch und nicht in allen Läden.

Hoffe Ablauf ist klar geworden,

Greetz Data

DataCool 6. Mär 2009 15:48

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
^^^???? ^^^^ Jetzt kein Kommentar mehr ?

Noch eine Zwischenfrage:

Würde es helfen, wenn die DB-Connection aus dem Dienst direkt ohne BDE gemacht werden ?

Greetz DAta

hoika 7. Mär 2009 10:05

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
Hallo,

solange du nicht weisst, wo der Fehler ist,
kann man das nicht beantworten.
Schon mal an Loggen in eine externe Textdatei gedacht ?


Heiko

neo4a 7. Mär 2009 10:34

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
@Heiko,

es wird ihm nicht viel nutzen, die Aktivitäten zu loggen. Das ist sehr aufwändig und bei seinem Szenario kaum nachzuvollziehen. Ich halte es da lieber mit Jason Wharton (IBObjects): Watch your Transactions! Firebird weigert sich zum Beispiel auch, einen Satz einzufügen bei einer Primary Key violation. Tritt niemals auf, wenn sie generell per Generator in Triggern gesetzt werden, aber das setzt ja der OP nicht ein.

Wenn ich nun den Ablauf richtig deute, gibt es praktisch keine Edits oder Deletes, nur Inserts. Wie werden dann die PK ermittelt? Beim Schreiben in welche Tabelle bleiben denn die Clients hängen? Hier würde ich meine Applikation etwas "gesprächiger" machen.

Der OP versorgt uns leider nur bruchstückweise mit Infos und vertraut auf die gut geputzten Glaskugeln der Mitleser.

--
Andreas

DataCool 7. Mär 2009 17:06

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
@Heiko:
Neo hat Recht per Logging kommt man dem Fehler nicht zu Rande.
Die Query bekommt auch keinen Fehler, ich finde zumindest in meinen LOgfiles keinen.
Der neue oder geänderte Datensatz wird einfach nicht gespeichert.

@Neo:
Da es sich bei der Gui-DB(DB1) um eine DB handelt die Zentral gemerched wird,
werden die PK anhand von Nummernkreisen berechnet abhängig von der ID des Standorts.
Ermittelt mit:
"Select max(xyz) from Tblxyz where (xyz > blamin) and (xyz < blaMax)"
Das Ergebnis dann + 1 ergibt die neue ID.

Und ja Neo beim Import den der Dienst durchführt gibt es zu 95% nur Inserts,
allerdings auch ein paar Updates da die Daten des Exports nicht unbedingt in einem Stück kommen.

Beim Speichern des SQL-Befehle gibt es nur Inserts.

Beim Thread der aus dem Dienst zum RZ des SQLs syncronisiert gibt es nur Updates(zu bearbeitene Datensätze werden via Flag markiert),
dann sequentiell übertragen und danach alle markierten Datensätze gelöscht.

Die Fehler treten laut Kundenaussagen aber nachher bei Stammdaten des Programms auf, die bei dem ganzen Kram nicht angepackt werden,
Oder es wird gar nichts mehr gespeichert.

Abhilfe bringt dann wie gesagt Neustart des Rechners, oder meine App beenden, meinen Dienst beenden und Firebird Dienst neu starten.

Habe das ganze jetzt soweit geändert das jedes TDatabase in meinem Dienst in einer eigenen Session läuft,
denke bin heute Abend soweit ein paar Tests zu fahren.

Wenn Ihr noch mehr Infos braucht, sagt wie ich Licht ins Dunkle bringen kann.

Greetz Data

neo4a 7. Mär 2009 17:48

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
Auch wenn es vielleicht nicht Dein primäres Problem ist: Die Art, wie Du den PK ermitteln lässt, ist in einer Mehrbenutzerumgebung wirklich völlig ungeeignet. Es sind unter allen Umständen Generatoren zu benutzen, da nur sie außerhalb einer Transaktion verwaltet werden. (Bitte nicht darüber diskutieren, sonder Helen Borries Firebird-Buch lesen.) Auch mit Generatoren kann man PK unter Berücksichtung von Nummernkreisen verwalten, damit Multipoint-Replikationen funktionieren. Ein alternativer Ansatz sind GUID als PK, aber das führt jetzt wirklich am Thread-Thema vorbei.

Deine Schilderung der Probleme lässt mich mutmaßen, dass bei Deinen Clients schlicht die Verbindung zur DB abbricht. Vielleicht stürzt sogar der FB-Server ab und es merkt keiner, weil der Guardian gleich wieder startet. Das steht in den Server-Logs oder im Ereignisprotokoll (ich hoffe, Du fährtst nicht noch Win9x/Me-Rechner). Oder es gibt ein Transaktions-Timeout und die BDE versagt.

Was die BDE anbelangt, so kann ich nur schwer helfen, denn ich setze sie nicht ein.

Weitere lustige Fehlerquellen sind unterschiedliche FB-DLL (gds32.dll) auf Client(s) und Server oder gemischte Connections (local,TCPIP). Letzteres führt auch gerne zu DB-Defekten.

--
Andreas

DataCool 7. Mär 2009 18:21

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
@neo:
Thema ID Vergabe hast Du absolut recht, lokal wird aber definitiv immer nur mit einem PC gearbeitet.

Die Idee mit dem kurzzeitigen Verbindungsabbruch werde ich mal nachgehen, das könnte eine logische Erklärung sein,
denn der Firebird-Server geht beim Import der Kassendaten so in die Knie(CPU-Last maximum),
das vielleicht die Gui-App Ihre Connection verliert.

^^ Werde ich prüfen ^^

Thx & Greetz DAta

neo4a 8. Mär 2009 16:16

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
Auch wenn Du nur mit einem PC arbeitest, hast Du mit der Client-Applikation und dem Dienst praktisch eine Mehrbenutzerumgebung. Da greifen alle Gefahren bei der PrimaryKey (PK)- Ermittlung.

Wenn also Dein Dienst seine Transaktion nach dem Insert noch nicht beendet hat, wird die Applikation in dieser Zeit per SQL-Max() einen PK- Wert bekommen, der aber bereits vom Dienst verbraucht wurde. Das ist ein typisches Deathlock- Szenario, das man häufig nur durch Dienst-Neustart (und Datenverlust!) lösen kann.

Und weil ich so schön am Erklären bin: Genau die Transaktionen sind auch der Grund, weshalb gerade beim Import (also Mengen- Inserts) ein FB- Server in die Knie gezwungen werden kann. Hier macht ein erfahrener Programmierer nach einer Anzahl von Inserts (z.B 100 oder 1000) ein "Commit work;" und passt auf, das keine Transaktion länger dauert als nötig (Stichwort OAT - oldest active transaction).

Viel Erfolg.

--
Andreas

DataCool 8. Mär 2009 20:36

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
@neo:
Gebe mich geschlagen, war nicht das beste Konzept damals ist auch schon über 8 Jahre her die erste Version.
Das Problem scheint sich auch erst jetzt wirklich bemerkbar zu machen, seitdem ich die SQL-Statements zur
Übertragung sichere.
Denke auch schon länger darüber nach die DB zu wechseln bzw. auf Firebird 2 umzusteigen.
Allerdings muss ich die Umstellung automatisiert in meine Online-Update Routine einbauen,
den ca. 120 Läden per Hand zu aktualisieren(nebenberuflich) ist doch etwas schwierig.
Für die Automatisierung habe ich leider noch keine ausgearbeitetes Konzept.

Deshalb war ich auf der Suche nach einer "Quick & Dirty" Lösung um das "Problem"
bis zum großen Update vom Hals zu haben.

Das einzige was mir im Moment spontan einfällt ist,
den Table zum SQL-Logging aus DB1 zu entfernen und in eine dritte neue DB(mit SP und Generator zur ID Erzeugung) zu portieren.
So würde die Client GUI nur in DB1 Lesen und schreiben.
Der Dienst würde die Import Daten in DB2 schreiben.
Und in DB3(nur ein Table zum SQL logging) würden beide Lesen und schreiben, allerdings wäre die ID Generierung durch den Generator dann geschützt.

Oder hast Du eine noch bessere Idee ?!

Greetz Data

neo4a 9. Mär 2009 09:08

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
Sorry, aber diese Konzepte waren schon bekannt, als ich meine WaWi vor 12 Jahren mit Interbase 5.6 produktiv schaltete, die auch heute noch entwickelt wird (jetzt aber mit FB 1.5).

Weitere Datenbanken zu benutzen, halte ich nicht für sinnvoll: in DB3 kommt eh alles wieder zusammen.

Was hälst Du davon, einen Generator IMPORT zu benutzen, der den Status des Imports angibt?

Ist IMPORT = 0, dann kann man in der Client- Anwendung normal arbeiten. Bei Inserts wird IMPORT=1 gesetzt, bei abgeschlossener Transaktion wieder auf 0. Arbeitet Dein Dienst, dann setzt er als erstes IMPORT=1 (wenn IMPORT=0 ist), ansonsten wird eben eine Zeit gewartet. Sobald IMPORT=1 gesetzt werden konnte, arbeitet der Dienst einen Teil der Import-Datei ab (vielleicht auch nur 1 Zeile). Anschließend setzt er IMPORT=0, damit am Client zwischenzeitliche Inserts möglich sind. Stellst Du mit IMPORT den prozentualen Fortschritt des Import-Dienst dar, so kannst Du sogar im Client den Status bekannt geben (wenn gewünscht).

Das ist nur ein Roh- Konzept eines partnerschaftlichen und nicht blockierenden Dienstes, wobei die Client-App. die Priorität behält. Natürlich lässt sich das auch anders realisieren, aber Du wolltest es ja "schnell und schmutzig".

Deine Überlegung FB zu ersetzen, bringt m.E. nicht viel. Gewinnen könntest Du, indem Du moderne API-Komponenten einsetzt. Ich benutze von Anfang an IBObjects, das seinerzeit einzigartig war. Du hast heute die Wahl zwischen weiteren Bibliotheken, die alle ihren Charme haben.

--
Andreas

mkinzler 9. Mär 2009 09:33

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
Nur werden die IBObjects nicht mehr zufriedenstellend weiterentwickelt

neo4a 9. Mär 2009 10:25

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
In der Tat fehlt zurzeit die D2009- Unterstützung. Es gibt aber aus den letzten Tagen eine Statement, dass einiges klärt und die Verfügbarkeit ankündigt.

Ansonsten ist das mit der Weiterentwicklung so eine Sache. IBO implementiert ja einige Techniken, die u.a. gerade das Tabellen- Browsen in großen Datenbeständen einfach und performant gestaltet. Auch die Dataset-Focus- und QBE (Query By Example)- Technik ist bemerkenswert. Alle diese Sachen sind primär von der Firebird-Version unabhängig und bis (m.W.) D2007 verfügbar. Ich habe z.B. meine Entwicklungsumgebung derzeit auf D7,IBO4.1 und FB1.5 eingefroren, weil bei langlaufenden Projekten die Zuverlässigkeit weit höhere Priorität hat, als die Unterstützung der letzten Features von Datenbank und IDE.

Ich erinnere mich in diesem Zusammenhang nur ungern an die Zeit, als ich bei auftretenden Fehlern nicht wusste, ob es mein Design-Fehler, eine "Eigenheit" von Interbase/Firebird oder ein IBO-Problem war: viel zu häufig war es eine Kombination aus allem ;)

--
Andreas

mkinzler 9. Mär 2009 10:38

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
Die IBO-Entwicklung stagniert schon länger. Es gibt aber auch noch Alternativen wie IBDAC und FIBPlus, welche aktiver weiterentwickelt werden

neo4a 9. Mär 2009 22:34

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
@mkinzler
Du hast Recht: Es gibt Alternativen beim DB-Zugriff auf FB. Oberflächlich gesehen sogar mehr als 2.
Du bist bei der IBO- Entwicklung vielleicht nicht ganz auf dem Laufenden.

--
Andreas

hoika 10. Mär 2009 08:11

Re: Mehrere DB-Verbindungen aus Dienst überfordern Firebird
 
Hallo,

um noch mal zum Hauptproblem zu kommen,
gibt es schon Neuigkeiten (eigenes TSession) ?

PS:
Ich habe hier auch noch ne BDE-FB-Leiche im Keller,
die noch Änderungen lechzt ... ;)
(FIBPlus ist schon gekauft und lungert auf der Platte rum.)


Heiko


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:55 Uhr.

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 by Thomas Breitkreuz