AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi FireDac ODBC Query bringt alte Daten
Thema durchsuchen
Ansicht
Themen-Optionen

FireDac ODBC Query bringt alte Daten

Ein Thema von fisipjm · begonnen am 24. Aug 2022 · letzter Beitrag vom 31. Aug 2022
Antwort Antwort
Seite 1 von 2  1 2      
fisipjm

Registriert seit: 28. Okt 2013
251 Beiträge
 
#1

FireDac ODBC Query bringt alte Daten

  Alt 24. Aug 2022, 16:02
Datenbank: ODBC • Version: 3.0 • Zugriff über: Odbc / FireDac
Hi,

ich habe ein Problem bei dem ich nicht wirklich dahintersteige, irgend eine Einstellung ist wahrscheinlich falsch, aber ich finde sie nicht

Folgender Aufbau. Ich habe eine FDConnection, die geht auf eine bestehende ODBC Verbindung (DBMS Firebird, sollte ja aber eigentlich egal sein, wegen ODBC)
Hab ein Datenmodul in dem ich die Connection und 2 Querys liegen habe.
Alles wunderbar soweit.

Die erste Query frägt die Tabelle nach einer Spalte ab. Nenn wir die Tabelle Nummernkreise und die Spalte Zähler.

Erster Query Ablauf sieht also so aus:

Delphi-Quellcode:
procedure HolDieNummer;
begin
Query1.sql := 'Select zaehler from Nummernkreise where Spalte1 = :Kriterium1 and Spalte2 = :Kriterium2';
Query1.parambyname('Spalte1').AsString:='Hotehü';
Query1.parambyname('Spalte2').AsString:='Bliblablubb';
Query1.open;
if Query1.isEmpty then
  raise Exception.create('Mach nicht so, dass kann gar nicht passieren!!');

GlobaleNummer := Query1.fieldbyname('zaehler').asInteger;
Query1.close;
end;
Die Kriterien begrenzen die Abfrage immer auf genau einen Datensatz.
Erster durchlauf alles Toll, ich bekomme z.B. Die Zahl 1234 zurück.
Die Zahl nehme ich addiere 1 und speichere sie mit der 2. Query in die gleiche Tabelle zurück. Das geht so:

Delphi-Quellcode:
Query2.sql := 'Select zaehler from Nummernkreise where Spalte1 = :Kriterium1 and Spalte2 = :Kriterium2';
Query2.parambyname('Spalte1').AsString:='Hotehü';
Query2.parambyname('Spalte2').AsString:='Bliblablubb';
Query2.open;
Query2.Edit;
Query2.Fieldbyname('zaehler').asinteger := GlobaleNummer+1;
Query2.Post;
Wenn ich jetzt in die Datenbank schaue dann steht in der Datenbank die 1235 drin. Alles fein. Lass ich jetzt aber die Funktion in einer SChleife lauf dann wirft mir "HoldieNummer" immer 1234 als Ergebnis raus und ich versteh nicht warum. Wenn ich das Programm beende und wieder neu aufrufe, bringt mir die Procedure 1235 als Ergebnis und beim nächsten Neustart 1236 usw. aber innerhalb des gleichen Programmaufrufs nicht.
Es muss was mit der 1. Query zu tun haben, aber ich komm nicht drauf....

Grüße
PJM
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
2.825 Beiträge
 
Delphi 12 Athens
 
#2

AW: FireDac ODBC Query bringt alte Daten

  Alt 24. Aug 2022, 20:24
Hallo,

es gibt verschiedene ReadModi für den Umgang mit SQL Datenbanken.
Welche genau von welcher untersützt wird ist dabei unterschiedlich.
Aber manche (z. B. RepeatableRead) können zu genau sowas führen.

Ich bin mir nicht sicher ob das die Lösung ist, aber versuche doch
mal beim Schreiben ein Commit nachzuschieben. Dadurch sollte die
Transaktion beendet werden und evtl. führt dann das Lesen zum
wirklichen neu Einlesen des Wertes.

Grüße
TurboMagic
  Mit Zitat antworten Zitat
fisipjm

Registriert seit: 28. Okt 2013
251 Beiträge
 
#3

AW: FireDac ODBC Query bringt alte Daten

  Alt 25. Aug 2022, 06:37
Hallo,

es gibt verschiedene ReadModi für den Umgang mit SQL Datenbanken.
Welche genau von welcher untersützt wird ist dabei unterschiedlich.
Aber manche (z. B. RepeatableRead) können zu genau sowas führen.

Ich bin mir nicht sicher ob das die Lösung ist, aber versuche doch
mal beim Schreiben ein Commit nachzuschieben. Dadurch sollte die
Transaktion beendet werden und evtl. führt dann das Lesen zum
wirklichen neu Einlesen des Wertes.

Grüße
TurboMagic
Moin Turbo

das hatte ich tatsächlich schon versucht. Dann bekomme ich die Meldung das die Transactionskonfiguration auf Cached Updates stehen muss damit ein Commit gemacht werden kann. Außerdem steht der Wert ja bereits richtig in der Datenbank, wird also tatsächlich geschrieben. Wenn ich von "Außen" die gleiche Query auf die DB werfe, dann wird mir der neue Wert angezeit, nur meine Query zur Abfrage des alten wertes liefert mir noch den alten Wert.
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
2.825 Beiträge
 
Delphi 12 Athens
 
#4

AW: FireDac ODBC Query bringt alte Daten

  Alt 25. Aug 2022, 07:54
Hast du schon mal probiert statt mit ODBC direkt mit dem FireDAC Firebird Treiber auf die DB zuzugreifen?
  Mit Zitat antworten Zitat
fisipjm

Registriert seit: 28. Okt 2013
251 Beiträge
 
#5

AW: FireDac ODBC Query bringt alte Daten

  Alt 25. Aug 2022, 09:09
Hast du schon mal probiert statt mit ODBC direkt mit dem FireDAC Firebird Treiber auf die DB zuzugreifen?
Das möchte ich vermeiden. Aufgrund anderer Schnittstellen besteht der ODBC Dienst schon und ich muss mir keine Gedanken über die Verbindung machen.
Ich habe das Problem jetzt "gelöst". Beim erklären ist bei mir die Frage aufgekommen warum ich überhaupt 2 unterschiedliche Querys fürs lesen und schreiben nehme. Also hab ich sie unter einer Query zusammen gefasst. Die weis jetzt natürlich auch was sie schon geschrieben hat. Interessant wäre es trotzdem gewesen zu wissen woran es gelegen hat.
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.270 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: FireDac ODBC Query bringt alte Daten

  Alt 25. Aug 2022, 09:38
Hasllo,
es wurde doch bereits alles gesagt.

Query1 benutzt Transaktion1
Query2 benutzt Transaktion2
Query3 ist deine externe Abfrage

Die beiden kommen sich nicht ins Gehege dank des Transaktionsmanagements von Firebird.
Wenn nichts weiter eingestellt ist, gilt "Read Committed"

Wenn Query1 z.B. 10.000 Selects macht (Lagerinspektion) und Query2 "zwischendurch" einen Änderung am Lager vernimmt, interessiert das Query1 nicht.
Jeder arbeitet praktisch mit einer Kopie der DB zum Zeitpunkt des Starts der jeweiligen Transaktion.

Bei Query3 startest du (ohne es zu Wollen/Wissen) immer eine neue Transaktion, die Änderungen der vorherigen Queries sind also sichtbar, sofern sie committed sind.

Lösung.
Du muss bei den Queries explizit ein StartTransaction/Commit machen.
Heiko
  Mit Zitat antworten Zitat
fisipjm

Registriert seit: 28. Okt 2013
251 Beiträge
 
#7

AW: FireDac ODBC Query bringt alte Daten

  Alt 25. Aug 2022, 10:06
Hasllo,
es wurde doch bereits alles gesagt.

Query1 benutzt Transaktion1
Query2 benutzt Transaktion2
Query3 ist deine externe Abfrage

Die beiden kommen sich nicht ins Gehege dank des Transaktionsmanagements von Firebird.
Wenn nichts weiter eingestellt ist, gilt "Read Committed"

Wenn Query1 z.B. 10.000 Selects macht (Lagerinspektion) und Query2 "zwischendurch" einen Änderung am Lager vernimmt, interessiert das Query1 nicht.
Jeder arbeitet praktisch mit einer Kopie der DB zum Zeitpunkt des Starts der jeweiligen Transaktion.

Bei Query3 startest du (ohne es zu Wollen/Wissen) immer eine neue Transaktion, die Änderungen der vorherigen Queries sind also sichtbar, sofern sie committed sind.

Lösung.
Du muss bei den Queries explizit ein StartTransaction/Commit machen.
Hi Hoika,

danke für die Erklärung. Wann endet ein Transaktion bei Firedac (Firebird?) Ich mache ja breits ein Open/Edit/Post/Close und bei der anderen Query ebenfalls ein Open/Close.

Ich wäre davon ausgegangen das mit einem Close alle offenen Transactions geschlossen werden. Beim nächsten Loop lauf mache ich ja wieder ein Open auf die Query, zwar mit den gleichen Parametern, aber eben wieder mit einem "frischen" Open. Wie sage ich der Transaction das sie sich die Daten jetzt bitte neu vom Server ziehen darf? Ein Commit wird mir verweigert mit dem hinweis das ich die Funktion CachedUpdates nicht aktiv hab, ergo wäre es nichts nötig?
  Mit Zitat antworten Zitat
Frickler

Registriert seit: 6. Mär 2007
Ort: Osnabrück
563 Beiträge
 
Delphi XE6 Enterprise
 
#8

AW: FireDac ODBC Query bringt alte Daten

  Alt 25. Aug 2022, 12:19
Wann endet ein Transaktion bei Firedac (Firebird?) Ich mache ja breits ein Open/Edit/Post/Close und bei der anderen Query ebenfalls ein Open/Close.
Bei Firebird müssen Transaktionen explizit committed werden. Wird einfach die Verbindung geschlossen (Programm beenden), hängt es von den Datenbankkomponenten ab, ob das ein Commit oder Rollback wird.
Erst in Firebird 4 gibt es auch von der Datenbankseite die Möglichkeit, AutoCommit zu konfigurieren.

AutoCommit wäre in diesem Fall aber auch falsch. Was ist denn, wenn zwischen "HolDieNummer" und "SetzDieNummer" jemand anders die Nummer erhöht? Da müsste "SetzDieNummer" als 3. Parameter den vorherigen Wert der Nummer abfragen. Also nur erhöhen, wenn zwischendurch niemand anders erhöht hat.

P.S.: warum nicht alles in einem Rutsch?
Code:
UPDATE nummernkreise SET zaehler = zaehler + 1
WHERE Spalte1 = :Kriterium1 and Spalte2 = :Kriterium2
RETURNING OLD.zaehler
(vorausgesetzt, das geht mit ODBC)

Geändert von Frickler (25. Aug 2022 um 12:32 Uhr)
  Mit Zitat antworten Zitat
fisipjm

Registriert seit: 28. Okt 2013
251 Beiträge
 
#9

AW: FireDac ODBC Query bringt alte Daten

  Alt 26. Aug 2022, 11:05
Wann endet ein Transaktion bei Firedac (Firebird?) Ich mache ja breits ein Open/Edit/Post/Close und bei der anderen Query ebenfalls ein Open/Close.
Bei Firebird müssen Transaktionen explizit committed werden. Wird einfach die Verbindung geschlossen (Programm beenden), hängt es von den Datenbankkomponenten ab, ob das ein Commit oder Rollback wird.
Erst in Firebird 4 gibt es auch von der Datenbankseite die Möglichkeit, AutoCommit zu konfigurieren.

AutoCommit wäre in diesem Fall aber auch falsch. Was ist denn, wenn zwischen "HolDieNummer" und "SetzDieNummer" jemand anders die Nummer erhöht? Da müsste "SetzDieNummer" als 3. Parameter den vorherigen Wert der Nummer abfragen. Also nur erhöhen, wenn zwischendurch niemand anders erhöht hat.

P.S.: warum nicht alles in einem Rutsch?
Code:
UPDATE nummernkreise SET zaehler = zaehler + 1
WHERE Spalte1 = :Kriterium1 and Spalte2 = :Kriterium2
RETURNING OLD.zaehler
(vorausgesetzt, das geht mit ODBC)
Gute Punkte. Zum Thema wenn jemand dazwischend eine Nummer holt. Ja, in der Theorie möglich, in der Praxis spielt sich die Abarbeitung im Millisekunden Bereich ab.
Gute Idee mit der Update und Retruning methode, allerdings muss ich die Nummer noch in eine andere Tabelle schreiben und darf die Nummer in den Nummernkreisen erst updaten wenn das Schreiben auch tatsächlich funktioniert hat.

Was ich nicht verstehe ist, ein Commit betrifft doch normal nur das Updaten. Das Updaten funktioniert aber, alleine die Select abfrage zum abrufen holt den alten wert. Der neue Wert steht zu dem Zeitpunkt aber definitiv schon der Datenbank. Ich glaube also nicht das es an dem Commit liegt.
  Mit Zitat antworten Zitat
Frickler

Registriert seit: 6. Mär 2007
Ort: Osnabrück
563 Beiträge
 
Delphi XE6 Enterprise
 
#10

AW: FireDac ODBC Query bringt alte Daten

  Alt 26. Aug 2022, 16:20
Was ich nicht verstehe ist, ein Commit betrifft doch normal nur das Updaten. Das Updaten funktioniert aber, alleine die Select abfrage zum abrufen holt den alten wert. Der neue Wert steht zu dem Zeitpunkt aber definitiv schon der Datenbank. Ich glaube also nicht das es an dem Commit liegt.
Bei Firebird müssen auch SELECTs committed werden (oder ein Rollback).

Wenn Du gar keine Transaktionsanweisungen verwendest, passiert folgendes: beim Starten des Programms öffnet die Verbindungskomponente eine Transaktion. Und die ist dann so lange offen, bis Du sie explizit committest, oder die Verbindung wieder schließst. Da hängts dann von den Einstellungen ab, ob ein Commit oder Rollback ausgeführt wird. Viele Verbindungskomponenten bieten eine Property "AutoCommit", mit der wird jedes Select und jede andere Anweisung automatisch committed. Damit sich Select-Fenster dann nicht einfach schließen, ist das kein normaler Commit, sondern ein sog. CommitRetaining. Das heißt, es wird committed und danach sofort eine neue Transaktion gestartet.

Jetzt wird auch klar, warum "HolDieNummer" niemals die neue Nummer holt - weil Du Dich immer in der gleichen Transaktion bewegst, und Firebird kein "Dirty Read" (uncommittete Daten anzeigen) beherrscht.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:28 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