AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Firebird 3.0 in einer SP (Multiuser-Umfeld) ein Wert ändern
Thema durchsuchen
Ansicht
Themen-Optionen

Firebird 3.0 in einer SP (Multiuser-Umfeld) ein Wert ändern

Ein Thema von Kostas · begonnen am 8. Mai 2022 · letzter Beitrag vom 9. Mai 2022
Antwort Antwort
Benutzerbild von IBExpert
IBExpert

Registriert seit: 15. Mär 2005
695 Beiträge
 
FreePascal / Lazarus
 
#1

AW: Firebird 3.0 in einer SP (Multiuser-Umfeld) ein Wert ändern

  Alt 9. Mai 2022, 07:38
So als Konzept wie man das verhindern kann, wenn man das unter High Load realisieren muss:

1. Erstelle dir eine Tabelle mit chargennummer auf reserve (als zB sind da die nächsten x tausend verfügbaren chargennummer schon drin). Diese hat dann zB ein timestamp, wann die vergeben wurde
2. Wenn du eine Chargenummer brauchst, dann sucht deine prozedur über folgende weg eine heraus
3. übergeordnete sp ohne exception handling when any GetCharge
-diese ruft mit einer for select schleife alle chargen ab, die im vergeben timestamp null hat
4. über eine extra sp mit exception handling when any machst du das den eintrag
create procedure SetCharge(chargenr integer)
returns (res char(1))
as
begin
update charge set charge.vergeben=current_timestamp where charge.chargenr=:chargenr;
res='T';
when any do res='F';
end;
5. mit allen results die du in der GetCharge in der for select into schleife free chargenumer geholt hast machst du ein execute procedure SetCharge RETURNING_VALUES mit der chargenr als input sol lange bis die irgendwann man T zurück gibt, dann reicht ein break um deine for select schleife zu beenden, der timestamp ist für diese bisher frei charge gesetzt und egal ob unter high load jemand anders diese oder andere in lang laufenden transaktion auch setzt und evtl sogar rollback macht ist egal, weil keiner dadurch einen deadlock bekommt.

der code da oben ist einfach so runtergetippt, daher sicherlich hier und da evtl fehlerhaft, sollte aber zu schaffen sein, das umzusetzen
Holger Klemt
www.ibexpert.com - IBExpert GmbH
Oldenburger Str 233 - 26203 Wardenburg - Germany
Firebird 5 Update und Know-how Workshop – 28.8.-29.08.2025 64546 Mörfelden - Walldorf

Geändert von IBExpert ( 9. Mai 2022 um 07:54 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von MyRealName
MyRealName

Registriert seit: 19. Okt 2003
Ort: Heilbronn
698 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Firebird 3.0 in einer SP (Multiuser-Umfeld) ein Wert ändern

  Alt 9. Mai 2022, 07:49
Es gibt da noch die globalen Variablen, die zur Connection oder Session gehören. Da kann man über die Tabelle auch die der anderen Connections/sessions sehen und auslesen. Könnte man anlegen, falls sie nicht da ist und löschen wenn man fertig ist. Und darüber dann sagen, welche Chargennummer man da gerade nutzt. wenn das mehrere Sessions sind, die sowas machen, dann einfach nur die größte einer fremdsession (also wo SessionId halt nicht die eigene ist) raussuchen und dann die nächste nehmen und selbst die Variable dann für die eigene Session anlegen. Und löschen, wenn man fertig ist.
  Mit Zitat antworten Zitat
Benutzerbild von IBExpert
IBExpert

Registriert seit: 15. Mär 2005
695 Beiträge
 
FreePascal / Lazarus
 
#3

AW: Firebird 3.0 in einer SP (Multiuser-Umfeld) ein Wert ändern

  Alt 9. Mai 2022, 07:58
Es gibt da noch die globalen Variablen, die zur Connection oder Session gehören. Da kann man über die Tabelle auch die der anderen Connections/sessions sehen und auslesen. Könnte man anlegen, falls sie nicht da ist und löschen wenn man fertig ist. Und darüber dann sagen, welche Chargennummer man da gerade nutzt. wenn das mehrere Sessions sind, die sowas machen, dann einfach nur die größte einer fremdsession (also wo SessionId halt nicht die eigene ist) raussuchen und dann die nächste nehmen und selbst die Variable dann für die eigene Session anlegen. Und löschen, wenn man fertig ist.
Unter High Load ist das kein echter Lösungsansatz, weil rollbacks oder exceptions die sessionvariablen dann nie wieder freigeben würden, daher würde ich das so nicht machen
Holger Klemt
www.ibexpert.com - IBExpert GmbH
Oldenburger Str 233 - 26203 Wardenburg - Germany
Firebird 5 Update und Know-how Workshop – 28.8.-29.08.2025 64546 Mörfelden - Walldorf
  Mit Zitat antworten Zitat
Kostas

Registriert seit: 14. Mai 2003
Ort: Gerstrhofen
1.115 Beiträge
 
Delphi 12 Athens
 
#4

AW: Firebird 3.0 in einer SP (Multiuser-Umfeld) ein Wert ändern

  Alt 9. Mai 2022, 08:42
Vielen Dank für die Antworten,

das klingt alles richtig kompliziert.
Eigentlich habe ich nach einer Konstruktion gehofft, die vor dem Update prüfen kann ob der Record, beschreibbar ist. Wenn nicht, selbständig warten bis er beschreibbar ist und fertig. In diesem speziellen Fall ist der einzige Initiator der die ChargenNr schreibt diese eine einzige SP. Das Problem ist nur, diese SP kann von zwei Client gleichzeitig aufgerufen werden und so den deadlock produzieren. In meiner SP mit dem auslesen, upadten, wieder auslesen und vergleichen ist eigentlich alles Mist. Ist nur aus Verzweiflung entstanden.

@Holger: Es sind mehrere tausend Artikel die jeweils eine eigene ChargenNr die NUR fortlaufend ist, haben. Die Tabelle Chargen ist absichtlich 1:1 über den PK und ohne FK des Artikels und beinhaltet NUR die ChargenNr sonst nichts, damit der Record mit der ChargenNr beschrieben werden kann unabhängig vom Artikel möglichst ohne deadlock. Sobald ein Artikel angelegt wird, wird der Record in Chargen angelegt mir ChargenNr = null.
Dein Vorschlag mit der zusätzlichen Tabelle die für jeden Artikel mehrere Chargennummer vorhalten soll habe ich nicht verstanden. Vermutlich passt das auch nicht zu meinem Fall. Leider habe ich das nicht gleich erwähnt und habe dich möglicherweise in die Irre geführt, sorry dafür. Ich dachte so eine "Warten" Konstruktion gibt es, nur ich kenne sie nicht.

Wichtig ist, ich habe keine Möglichkeit im Client irgend etwas zu verändern da es fremde Maschinensteuerungen sind. Ich kann also keine Exception im Client abfangen. Es muss alles in der SP passieren und die SP muss durchlaufen und die nächste gespeicherte ChargenNr ausgeben. Das beste währe gewesen, ich hätte für jeden Artikel einen Generator angelegt. Da es viele tausend Artikel sind wollte ich dafür die Generatoren nicht missbrauchen.

Gruß Kostas
  Mit Zitat antworten Zitat
Benutzerbild von IBExpert
IBExpert

Registriert seit: 15. Mär 2005
695 Beiträge
 
FreePascal / Lazarus
 
#5

AW: Firebird 3.0 in einer SP (Multiuser-Umfeld) ein Wert ändern

  Alt 9. Mai 2022, 10:41
du kannst mit einer wait transaction auch warten, hängt von den DB Komponenten ab, wo du das wie einstellst.
das blockt aber nur so lange bis klar ist ob die konkurrierende deadlock transaction committed ist, weil du in dem
fall erst dann die exception bekommst, die du auch bei nowait direkt bekommen hättest. nur bei rollback der konkurrierenden
deadlock transaction ginge es bei dir ohne exception weiter. Wenn die andere Transaktion aber warum auch immer stundenlang
dauert, dann wird es bei wait auch stundelang nicht weitergehen, daher eignet sich der ansatz nur selten.

Das Verfahren das ich dir geschildert hat ist 100% deadlock sicher und sorgt für eindeutigkeit schon in der db, du kannst das
aus einem trigger heraus machen oder vom client oder wo aus immer.

Im Rahmen unserer Hotlinepaket kann man so was auch mit meiner Hilfe per remote Session direkt in die db einbauen lassen
und sich dabei erklären lassen, das das überhaupt nicht kompliziert ist und das nachher auch selber so sieht
Holger Klemt
www.ibexpert.com - IBExpert GmbH
Oldenburger Str 233 - 26203 Wardenburg - Germany
Firebird 5 Update und Know-how Workshop – 28.8.-29.08.2025 64546 Mörfelden - Walldorf
  Mit Zitat antworten Zitat
Benutzerbild von MyRealName
MyRealName

Registriert seit: 19. Okt 2003
Ort: Heilbronn
698 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Firebird 3.0 in einer SP (Multiuser-Umfeld) ein Wert ändern

  Alt 9. Mai 2022, 12:01
Es gibt da noch die globalen Variablen, die zur Connection oder Session gehören. Da kann man über die Tabelle auch die der anderen Connections/sessions sehen und auslesen. Könnte man anlegen, falls sie nicht da ist und löschen wenn man fertig ist. Und darüber dann sagen, welche Chargennummer man da gerade nutzt. wenn das mehrere Sessions sind, die sowas machen, dann einfach nur die größte einer fremdsession (also wo SessionId halt nicht die eigene ist) raussuchen und dann die nächste nehmen und selbst die Variable dann für die eigene Session anlegen. Und löschen, wenn man fertig ist.
Unter High Load ist das kein echter Lösungsansatz, weil rollbacks oder exceptions die sessionvariablen dann nie wieder freigeben würden, daher würde ich das so nicht machen
Wenn die Session ungültig wird, werden dann nicht automatisch die Variablen gelöscht ? Oder könnte man einen Inner-Join zur Sessiontabelle machen und so sicher stellen, das ungültige Einträge ignoriert werden ?
  Mit Zitat antworten Zitat
Benutzerbild von IBExpert
IBExpert

Registriert seit: 15. Mär 2005
695 Beiträge
 
FreePascal / Lazarus
 
#7

AW: Firebird 3.0 in einer SP (Multiuser-Umfeld) ein Wert ändern

  Alt 9. Mai 2022, 16:59
Wenn die Session ungültig wird, werden dann nicht automatisch die Variablen gelöscht ? Oder könnte man einen Inner-Join zur Sessiontabelle machen und so sicher stellen, das ungültige Einträge ignoriert werden ?
User Session variablen schon, aber die sieht man woanders ja auch nicht, über mehrere Connections damit was Koordinieren bringt eine da nicht weiter
Holger Klemt
www.ibexpert.com - IBExpert GmbH
Oldenburger Str 233 - 26203 Wardenburg - Germany
Firebird 5 Update und Know-how Workshop – 28.8.-29.08.2025 64546 Mörfelden - Walldorf
  Mit Zitat antworten Zitat
jobo

Registriert seit: 29. Nov 2010
3.072 Beiträge
 
Delphi 2010 Enterprise
 
#8

AW: Firebird 3.0 in einer SP (Multiuser-Umfeld) ein Wert ändern

  Alt 9. Mai 2022, 20:53
Wie oft wird denn die OP aufgerufen und wie groß ist vom Workflow her die Wahrscheinlichkeit, dass 2 Aufrufe zeitgleich auf die gleich ChargenNr erfolgen?
Verdacht: Das ganze wird in einer Loop aufgerufen? (ChargenNr für eine Palette voll Artikel z.B.?)

Wenn ja oder nein, woher kommt der "High Load"? Gibt es einen? Diese OP für sich ist ja nicht besonders anstrengend (bei passender Indizierung).
Es gibt allerdings ein (klassisches?) Problem, die OP verändert Werte, die Teil der Where Bedingung sind.

Für eine einzige solche OP immer noch kein Ding, wenn der Client das in einer Loop rausballert oder mehrere Clients, dann wird es vielleicht eng.

Ich kenne firebird nicht gut, aber ich würde versuchen, das zu entzerren.
Update Kriterium ungleich Suchkriterium.

Außerdem sieht es anhand Deines SP Codes ein wenig so aus, dass die technische ID der Charge gleich der "Nutzlast" ist, was bedeuten würde, dass Du einen PK updatest. Das macht man eigentlich nie, so als Grundregel.

Gibt es irgendeine andere Spalte, die eine Identifizierung ermöglicht?
Gruß, Jo
  Mit Zitat antworten Zitat
Antwort Antwort


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 20:15 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