Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Keine Transaktion aktiv ?!? (https://www.delphipraxis.net/187247-keine-transaktion-aktiv.html)

OlafSt 11. Nov 2015 11:16

Datenbank: MSSQLExpress • Version: 14 • Zugriff über: ADO

Keine Transaktion aktiv ?!?
 
Hallo Freunde,

ich habe hier ein Phänomen, das mir dutzende Fragezeichen auf die Stirn zaubert - ich hab einfach keine Ahnung mehr, was ich noch machen soll.

Situation: Delphi XE4-Anwendung empfängt Binärdaten von Blackboxes, die in LKW eingebaut sind. Diese Daten werden dekodiert und als generalisierter Datenblock in eine TQueue<DataBlock> geschoben. Die Queue ist mit Critical Sections abgesichert, denn:

Ein gleichpriorisierter Thread schaut nun in der Queue nach Datenblocks. Findet er einen, wird dieser weiter aufbereitet und per SQL-Statement in eine SQL-Datenbank geschrieben. Da durchaus mehrere verschiedene Datenblöcke in der DB landen können, wird dieser gesamte Aufbereitungs- und Schreibvorgang in eine SQL-Transaktion verpackt. Geht alles gut, folgt ein CommitTrans, wenn nicht, ein RollbackTrans mit Protokollierung des Fehlers in einem Logfile. Die Datenbank ist eine SQL-Express 14-DB, also wahrlich kein Hexenwerk, wie auch das ganze System eigentlich kein Hexenwerk ist.

Diese Anwendung läuft nun seit Monaten bei den verschiedensten Kunden ohne Störungen und ohne Murren. Nur bei einem nicht. Bei diesem taucht in unregelmäßigen Abständen ein Error-Report von madExcept auf und es zeigt sich eine EOleException: Keine der Transaktionen ist aktiv. Es gibt noch zwei weitere mögliche Exceptions: "Fehler im TDS-Datenstrom" und "EOleException, Da der manuelle oder verteilte Transaktionsmodus aktiviert ist, kann keine neue Verbindung erstellt werden".

Ich kann mir das einfach nicht erklären, denn mein Exceptionhandler wird gar nicht erst aufgerufen. Auch kapiere ich nicht, wie da "keine Transaktion aktiv" sein kann - es gibt keine Chance, das BeginTrans zu umgehen, ebensowenig eine Chance, um das Commit bzw. Rollback herumzukommen (Mißgestaltete if-Abfragen, exit-Befehle irgendwo - alles sauber).

Der Rechner mit diesen Problemen hat ein Windows 7 Professional 64Bit mit allen Updates als Betriebssystem, 4GB Speicher, normale Festplatte... Alles völlig normal bis auf die CPU (ist ein Pentium G3260, Dual-Core).

Dieser Fehler tritt "einfach so" auf, es gibt keinen erkennbaren Grund. Ich laboriere nun seit 3 Wochen damit herum und habe keinen Schimmer, wonach ich da suchen soll.

Hat jemand von euch eine Idee ?

taveuni 11. Nov 2015 13:29

AW: Keine Transaktion aktiv ?!?
 
Wird die ADO Connection in dem Threadcontext erzeugt?

Bambini 11. Nov 2015 13:40

AW: Keine Transaktion aktiv ?!?
 
Von der TDS Meldung und EOleException scheint es ein SQL Server zu sein, in welche du die Daten schreibst.
Sind in einer der SQL Tabellen TDateTime oder Float Felder drin?

Wenn ja, lautet die Meldung evtl. so ähnlich:
Zitat:

Der eingehende Tabular Data Stream (TDS) für das RPC-Protokoll (Remote Procedure Call) ist nicht richtig. Parameter 17 (''): Der angegebene Wert ist keine gültige Instanz des float-Datentyps. Überprüfen Sie die Quelldaten im Hinblick auf ungültige Werte. Ein Beispiel für einen ungültigen Wert sind Daten eines numerischen Typs, deren Dezimalstellen den Wert für die Genauigkeit überschreiten.
Die Ursache ist ein z.B. ein leerer Parameter.

Wenn solch eine Exception auftritt, dann macht der SQL Server selbst einen Rollback, d.h. dein
Delphi-Quellcode:
Try...Except Rollback; end
läuft dann auf keine bestehende Transaktion mehr.

OlafSt 11. Nov 2015 14:29

AW: Keine Transaktion aktiv ?!?
 
Danke für diese ersten Anregungen.

Zitat:

Zitat von taveuni (Beitrag 1321147)
Wird die ADO Connection in dem Threadcontext erzeugt?

Nope. Ich erzeuge eine global verfügbare ADO-Connection, die dann von allen anderen benutzt wird. Dies ist zu 99,9% der schon angesprochene Thread. Bei Programmstart werden über die Connection Fahzeugdaten aus der Datenbank geholt bzw. neu hinzukommende Fahrzeuge abgespeichert. Es ist sicher, das die Fahrzeug-Infos wasserdicht von den im Thread begrabbelten Tabellen getrennt sind.

Zitat:

Von der TDS Meldung und EOleException scheint es ein SQL Server zu sein, in welche du die Daten schreibst.
Sind in einer der SQL Tabellen TDateTime oder Float Felder drin?
Richtig, ist ein MSSQL-Server. Es sind auch TDateTime-Felder und floats in den Tabellen vorhanden. Allerdings ist sichergestellt, das hier immer gültige Daten drin sind (notfalls halt 0.0). Außerdem: Würde die Exception dann nicht von mir gefangen werden ? Mein Code in abgespeckter, aber sonst korrekt laufender Form:

Delphi-Quellcode:
gConn.BeginTrans;
try
   if (HasGPS)
     WriteGPS(DataBlock);
   if (HasGSM)
     WriteGSM(DataBlock);
   [...]
   gConn.CommitTrans;
except
   //Exception im Log vermerken
   WriteLog('Exception');
   gConn.RollbackTrans;
end;
Würde also eine solche EOleException geworfen, müßte mein Exceptionhandler diese fangen und im Logfile vermerken. Stattdessen kommt madExcept hoch und zeigt einen Error-Report. Selbst wenn innerhalb des Exception-Handlers durch das RollbackTrans eine neue Exception ausgelöst würde, müßte ich das im Logfile sehen: Der LogWriter arbeitet ebenfalls mit einer Warteschlange und schreibt die Logeinträge niedrigpriorisiert in die Logfiles. Sobald also was in der Log-Queue landet, kommt es auch ins Logfile. Aber da ist nix.

Nichtsdestotrotz werde ich um das RollbackTrans mal ein "if gConn.InTransaction" legen, um da ganz sicher zu gehen.

taveuni 11. Nov 2015 14:40

AW: Keine Transaktion aktiv ?!?
 
Zitat:

Zitat von OlafSt (Beitrag 1321154)
Danke für diese ersten Anregungen.

Zitat:

Zitat von taveuni (Beitrag 1321147)
Wird die ADO Connection in dem Threadcontext erzeugt?

Nope.

Die ADO Connection (sowie auch z.b. Devart usw.) ist nicht Threadsave. Du musst diese im Thread erzeugen. Bei Devart kann man die globale dann Assignen. Möglicherweise bei ADO auch?

OlafSt 11. Nov 2015 14:55

AW: Keine Transaktion aktiv ?!?
 
Zitat:

Zitat von taveuni (Beitrag 1321157)
Die ADO Connection (sowie auch z.b. Devart usw.) ist nicht Threadsave. Du musst diese im Thread erzeugen. Bei Devart kann man die globale dann Assignen. Möglicherweise bei ADO auch?

Ach herrje ! Da hätte ich auch mal nach googeln können. Umso erstaunlicher ist es, das mir noch keines meiner anderen Programme (und es waren wirklich viele) bisher um die Ohren geflogen ist :twisted:

Danke für den Hinweis, ich bau das um und melde mich wieder, falls die Probleme weitergehen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:36 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz