Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Firbird Generator und Transaction (https://www.delphipraxis.net/216896-firbird-generator-und-transaction.html)

tkhandel 19. Mär 2025 12:11

Datenbank: Firbird • Version: 5 • Zugriff über: FD

Firbird Generator und Transaction
 
Hallo,

ich starte bei einer Belegerfassung eine Transaction (FDConnection.StartTransaction) für mehrere Tabellenoperationen.
Nach einem rollback wird die Belegerfassung abgebrochen und die Belegkopfdaten und Belegpositionsdaten werden auch erfolgreich
verworfen.
Der Generator allerdings wird nicht wieder zurück gesetzt so das mir bei einem Abbruch immer eine Belegnr verloren geht was ja nicht sein darf.
Kann ich irgendwo verfolgen woran das liegen könnte?

Frickler 19. Mär 2025 12:23

AW: Firbird Generator und Transaction
 
Die Generatoren laufen immer außerhalb der Transaktionssteuerung. Das ist auch so dokumentiert.

P.S.: Generatoren sind gedacht für künstliche Keys. Für eine Belegnummer würde ich einen anderen Mechanismus nutzen, z.B. eine eigene Tabelle.

tkhandel 19. Mär 2025 12:35

AW: Firbird Generator und Transaction
 
Hallo,

Danke für die schnelle Rückmeldung. Das hatte ich vorher so und ich dachte es wäre eine gute Idee das gleich in den Trigger einzubauen. :(
Also nehme ich wieder meine alte function.

IBExpert 19. Mär 2025 14:49

AW: Firbird Generator und Transaction
 
Zitat:

Zitat von tkhandel (Beitrag 1547275)
Hallo,

Danke für die schnelle Rückmeldung. Das hatte ich vorher so und ich dachte es wäre eine gute Idee das gleich in den Trigger einzubauen. :(
Also nehme ich wieder meine alte function.

bedenke bei deiner eigenen Funktion das ggf 2 transaktionen nahezu gleichzeitig eine nummer brauchen könnten und wenn du
dann den wert einer tabelle ausliest, diesen per update um 1 erhöht zurüschreiben willst, kann es je nach anzahl der user im
Netz dazu führen, das es ein deadlock gibt. auch einfach max ermitteln und eins höher zurückschreiben ist im netztwerk betrieb
sehr anfällig und dazu noch wird das erst beim kunden selbst im praxiseinsatz irgendwann mal passieren.

reale geschichte aus der vergangenheit: schlecht implementierte software beim kunden lief geichzeitig von 2 clients je einen
lieferschein an und aufgrund eines fehler ähnlich wie da oben haben die am ende zwar 2 lieferschein köpfe in den tabellen,
dummerweise waren aber auf einem davon gar keine positionen, auf dem anderen jedoch alle inkl welche die nix mit dem endkunden
zu tun hatten. Das fiel erst abends auf als ein Mitarbeiter der Kommissionierung mit dem leeren lieferschein zur IT kam und fragt
was das wohl sollte. Die datenprüfung zeigte, das ein LKW mit dem LS unterwegs war, der schon sachen abgeladen hatte, die bei dem
Endkunden nix zu suchen hatten.

Das passierte das erste mal nachdem die software schon ca ein jahr im Einsatz war. Ich war consultant bei denen für eine andere
software, hatte das dann aber mit denen zusammen schnell analysiert und die ursachen lokalisiert.

denk am besten immer an worst case, dann wirst du nicht negativ überrascht

in Firebird ist das per Generator einfach lösbar aber nur als eindeutige werte, lückenlos muss man anders machen, geht aber eigentlich
auch einfach.

TurboMagic 19. Mär 2025 23:42

AW: Firbird Generator und Transaction
 
Zitat:

Zitat von IBExpert (Beitrag 1547280)
in Firebird ist das per Generator einfach lösbar aber nur als eindeutige werte, lückenlos muss man anders machen, geht aber eigentlich
auch einfach.

Jetzt spannst du uns aber auf die Folter ;-)

Billa 20. Mär 2025 06:16

AW: Firbird Generator und Transaction
 
Ein (schon sehr alter) Ansatz für numerierte Belege :

Man speichert eine gewisse Anzahl Nummern mit Hilfe des Generators in einen "Vorrat".
Von dort holt man sich bei Bedarf für seine Transaktion die niedrigste ungesperrte Nummer und sperrt sie im Vorrat.

Wird Transaktion abgebrochen, hebt man einfach die Sperre wieder auf. Ansonsten wird die Nummer entfernt. Ein Trigger sorgt dafür, dass immer genug ungesperrte Nummern vorrätig sind. 50 Nummern waren bei nur drei Clients immer genug.

Dann ist die Folge der Nummern lückenlos, aber nicht zwingend chronologisch. Die Reihenfolge kann bei längeren Transaktionen durch Abbruch vertauscht sein. Das war für die damalige Aufgabenstellung aber nicht wichtig und wurde durch einen zusätzlichen Zeitstempel kenntlich gemacht.

Alternativ kann man statt zu sperren auch die Nummer sofort aus dem Vorrat entfernen und bei Abbruch der Transaktion wieder dort einfügen.

Wahrscheinlich gibt es aber noch bessere Methoden. 8-)

tkhandel 20. Mär 2025 10:47

AW: Firbird Generator und Transaction
 
Hallo,

eine spannende Diskussion die ich da losgetreten habe.
Ich habe aber eine ganz einfache Situation, da ich nur einen User an einer Kasse habe und die Kassen abends nur Ihre Daten übertragen und am
nächsten Tag wieder bei 0 anfangen( ausser die BON Nr die muss eben an jeder Kasse für sich weitergezählt werden).
ist ein Generator die sicherste Lösung.

Da ja keine zwei User eine Kasse bedienen können habe ich da mal über eine procedure gelöst die ich aufrufe wenn
der Kassiervorgang abgebrochen wurde.


SET TERM ^ ;

create or alter procedure PROC_BONGEN_DEC (
IST_ZAEHLER integer)
returns (
SOLL_ZAEHLER integer)
as
begin
ist_zaehler = GEN_ID( gen_bon_id, 0 );
Soll_Zaehler = (ist_zaehler - 1);
if (soll_zaehler >0) then
begin
ist_zaehler = gen_id(GEN_BON_ID, -(gen_id(Gen_Bon_Id, 0)));
soll_zaehler = gen_id(Gen_Bon_Id, :soll_zaehler);
end
suspend;
end^

SET TERM ; ^

Gibt es was das da gegen spricht ?

MyRealName 20. Mär 2025 10:54

AW: Firbird Generator und Transaction
 
Kannst Du eine nicht genutzte Nummer einfach als annuliert führen ? SO haben wir das in Kolumbien lösen können, da wird das vom Finanzamt scheinbar erlaubt (sagte mein Chef)

tkhandel 20. Mär 2025 11:05

AW: Firbird Generator und Transaction
 
Ich hatte das in einer Multiuser-Umgebung so gelöst, das ein erzeugter Beleg beim abrechen (automatisch) wurde, also
ein neuer Stornobeleg zum Ursprungsbeleg erzeugt wurde, das ist die einfachste Lösung da es nun ja nicht so oft vorkommt
und nach der Umstellung beim Kunden noch weniger wie vorher.

Bei Kassensystemen ist das nun eigentlich generell auch so das ein Beleg storniert werden muss um die
Nachvollziehbarkeit eines Kassenvorgangs zu gewährleisten zumal ja auch noch Positionsdaten des ersten Artikel
in der TSE gespeichert werden.

IBExpert 20. Mär 2025 11:22

AW: Firbird Generator und Transaction
 
wenn multiuser eh kein problem bei dir ist, dann ermittel die nächste nummer mit

select coalesce(max(nummer),0)+1 from tabelle where datum=current_date

mit einem desc index auf der nummer und dem datumsfeld (falls erforderlich weil datensätze von gestern in der tabelle bleiben)
geht das auch sehr schnell

wenn es eh bei 0 wieder losgeht ist der umweg über generator im singleuser mode unnötig kompliziert

tkhandel 20. Mär 2025 12:18

AW: Firbird Generator und Transaction
 
Hallo Holger,
ich hatte mich falsch oder besser gesagt Blöde ausgedrückt.
Die BON-Nr muss natürlich immer fortlaufend sein, deshalb der Generator bei der BonNr.
Ich hatte nur das Problem das ein Rollback alles zurück setzt nur den Generator nicht.

IBExpert 20. Mär 2025 12:52

AW: Firbird Generator und Transaction
 
Zitat:

Zitat von tkhandel (Beitrag 1547318)
Hallo Holger,
ich hatte mich falsch oder besser gesagt Blöde ausgedrückt.
Die BON-Nr muss natürlich immer fortlaufend sein, deshalb der Generator bei der BonNr.
Ich hatte nur das Problem das ein Rollback alles zurück setzt nur den Generator nicht.

wird dir beim generator aber immer so passieren, es klingt aber so das du da mittlerweile einen
weg gefunden hast. ich mach das aber meistens auch so wie von billa angedeutet

es gibt eine Tabelle in der der aktuelle wert drin steht für jede nummer die ich brauche
Code:
CREATE TABLE BRPNR (
    ID    BIGINT NOT NULL,
    TN    VARCHAR(32) COLLATE UNICODE,
    NR    integer,
    REUSE CHAR(1)
);
und es gibt eine wo ich werte ablege, die doch nicht benutzt wurde
Code:
CREATE TABLE BRPNRX (
    ID BIGINT NOT NULL,
    TN VARCHAR(32) COLLATE UNICODE,
    NR integer
);
auf den Tabellen die da oben Reuse 'T' haben erzeuge ich automatisiert trigger die in etwa so aussehen

Code:
CREATE OR ALTER trigger gutschrift_brp03 for gutschrift
active before delete position 32001
AS
BEGIN
  IF (COALESCE(OLD.NR,'')<>'') THEN
  begin
    INSERT INTO BRPNRX (TN, NR) VALUES ('GUTSCHRIFT', OLD.NR);
  end
END
Code:
CREATE OR ALTER trigger gutschrift_brp04 for gutschrift
active before insert position 32001
AS
BEGIN
  IF (COALESCE(NEW.NR,'')='') THEN
  begin
    --die folgenden 3 zeilen sind nur dann im trigger wenn reuse T
    SELECT FIRST 1 NR FROM BRPNRX where BRPNRX.TN='GUTSCHRIFT' order by NR into new.nr;
    if (new.nr is not null) then delete from brpnrx where BRPNRX.TN='GUTSCHRIFT' and nr=new.nr;
    else
    --ab hier dann auch ohne reuse, bei bedarf sogar schon immer beides mit autonomous transaction, damit das locking möglichst kurz dauert
    begin
      update brpnr set nr=nr+1 where brpnr.tn='GUTSCHRIFT';
      select nr from brpnr where brpnr.tn='GUTSCHRIFT' into new.nr;
    end
  end
  when any do begin
     while (new.nr is null) do
     execute procedure brpgetnrtryagain(new.id);
  end
END
es ist gegenüber der realen version stark vereinfacht weil ich da auch noch variablen als template drin hab wie [JJJJ] und diversen anderen kram, funktioniert so in der art aber seit mehr als 10 jahren in einem realen kundenprojekt

zeigt aber auch so schon wie das laufen kann. die Prozedur brpgetnrtryagain lass ich mal weg, die macht aber sinngemäss das gleiche wie der trigger und wiederholt das im fall von einem deadlock so oft mit einer execute statement. with autonomous transaction bis da ein wert ermittet wurde , falls es ein locking problem gab.

der code da oben ist einfach so runtergetippt, also keine gewähr auf compilierbarkeit


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:54 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-2025 by Thomas Breitkreuz