Firebird 5 demnächst RC

Produkt- und Serviceankündigungen zu Firebird.

Moderator: martin.koeditz

vr2
Beiträge: 219
Registriert: Fr 13. Apr 2018, 00:13

Ich hab den Effekt reproduziert gekriegt, der zur Einführung von ReadConsistency führte! Man muss zwar deutlicher werden, aber gut, das selber mal gesehen zu haben.

Testszenario: Zwei Flamerobin-Instanzen, damit man zwei separate Connections hat, die man parallel starten kann. Eine Quelltabelle tbl2 (num integer) mit 100000 Sätzen drin, und eine Zieltabelle tbl (num integer), leer. Ich hatte mir mal eine UDR sequencer geschrieben, um eine Reihe von Statements hintereinander oder parallel aus der Datenbank heraus ausführen zu können, eine Art Skriptplayer. Statements, die hintereinander ausgeführt werden sollen, werden darin mit einem '----' getrennt, ansonsten werden die Statements parallel ausgeführt. Mit der UDR hab ich getestet. Die serielle und parallele Skriptausführung kriegt man auf Anwendungsebene natürlich auch mit anderen Mitteln hin. Man muss halt nur bei den inserts für ausreichend action sorgen, sonst sieht man den Effekt nicht.

In jeder von den connections läuft also ein sequencer, der eine zählt immer schön nacheinander (die select count(*) werden nacheinander ausgeführt, siehe '----'), der andere sequencer schaufelt gleichzeitig zu den selects auf 10 connections parallel rein, jede von denen committet 100000 Sätze (nicht mehr, nicht weniger), Endergebnis in tbl müssten also 1 Mio Sätze sein, und, das ist der springende Punkt, Zwischenergebnisse der Zählung müssten Vielfache von 100000 sein:

con1:

Code: Alles auswählen

select * from sequencer('----', 
'select count(*) from tbl;
----
select count(*) from tbl;
----
select count(*) from tbl;
----
select count(*) from tbl;
----
select count(*) from tbl;
----
select count(*) from tbl;
----
select count(*) from tbl;
----
select count(*) from tbl;
----
select count(*) from tbl;
----
select count(*) from tbl;
')
con2:

Code: Alles auswählen

select * from sequencer('----', 
'insert into tbl select num from tbl2;
insert into tbl select num from tbl2;
insert into tbl select num from tbl2;
insert into tbl select num from tbl2;
insert into tbl select num from tbl2;
insert into tbl select num from tbl2;
insert into tbl select num from tbl2;
insert into tbl select num from tbl2;
insert into tbl select num from tbl2;
insert into tbl select num from tbl2;
')
Das ergibt bei der Zählconnection con1:

Code: Alles auswählen

PART	LINE	TASK				RESULT	STATUS	MESSAGE	SELECTS	INSERTS	UPDATES	DELETES	TASK_TIME	PART_TIME
1	1	select count(*) from tbl	0	ok	[null]	1	0	0	0	484	484
2	1	select count(*) from tbl	0	ok	[null]	1	0	0	0	484	484
3	1	select count(*) from tbl	0	ok	[null]	1	0	0	0	485	485
4	1	select count(*) from tbl	7457	ok	[null]	1	0	0	0	2828	2828
5	1	select count(*) from tbl	900136	ok	[null]	1	0	0	0	1906	1906
6	1	select count(*) from tbl	1000000	ok	[null]	1	0	0	0	781	781
7	1	select count(*) from tbl	1000000	ok	[null]	1	0	0	0	719	719
8	1	select count(*) from tbl	1000000	ok	[null]	1	0	0	0	641	641
9	1	select count(*) from tbl	1000000	ok	[null]	1	0	0	0	625	625
10	1	select count(*) from tbl	1000000	ok	[null]	1	0	0	0	562	562
Die count-Ergebnisse (Spalte result) 7457 und 900136 sind falsch, da immer nur 100000 Sätze als Ganzes committet werden.

Solange man Schreiben und Lesen schön hintereinander macht, erst füllen, dann lesen, hat man nie ein Problem. Aber wenn während einem Lesestatement committet wird, kann man ein Problem kriegen. Das dürfte auch der Grund sein, warum man bspw in ETL-Systemen kein Problem hat, denn dort organisiert man normalerweise den Ablauf selber. Da wird ja immer erst gefüllt und dann gelesen, nach selbst definierter Reihenfolge. Aber normalerweise wird nicht geschrieben, während etwas anderes liest. Und wenn, synct man das mit anderen Mitteln, wie bspw expliziten locks. Das hier kommt nur zum Tragen, wenn man ReadCommitted liest und währenddessen ohne weitere Koordination geschrieben und committet wird.

Mit ReadConsistency sieht der gleiche Test so aus:

Code: Alles auswählen

PART	LINE	TASK				RESULT	STATUS	MESSAGE	SELECTS	INSERTS	UPDATES	DELETES	TASK_TIME	PART_TIME
1	1	select count(*) from tbl	0	ok	[null]	1	0	0	0	500	500
2	1	select count(*) from tbl	0	ok	[null]	1	0	0	0	422	422
3	1	select count(*) from tbl	0	ok	[null]	1	0	0	0	500	500
4	1	select count(*) from tbl	300000	ok	[null]	1	0	0	0	766	3328
5	1	select count(*) from tbl	800000	ok	[null]	1	0	0	0	750	750
6	1	select count(*) from tbl	1000000	ok	[null]	1	0	0	0	579	579
7	1	select count(*) from tbl	1000000	ok	[null]	1	0	0	0	531	531
8	1	select count(*) from tbl	1000000	ok	[null]	1	0	0	0	453	453
9	1	select count(*) from tbl	1000000	ok	[null]	1	0	0	0	437	437
10	1	select count(*) from tbl	1000000	ok	[null]	1	0	0	0	407	407
So ist es korrekt. Nur Vielfache von 100000 (die 300000 und 800000 in Spalte result) werden gezählt, weil nur 100000 auf einmal committet werden.

bfuerchau, das bedeutet für Deine Logik, dass Du nur die Stellen abklopfen musst, wo während einer ReadCommitted Leseaktion auf den von der Leseaktion betroffenen Daten von anderen TXen geschrieben und committet wird. Wenn das nie der Fall ist, hast Du nach wie vor kein Problem.

Martin, siehst Du eine Möglichkeit, in phpBB Tabellenanzeige zu unterstützen?

Grüße, Volker
bfuerchau
Beiträge: 490
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

Wahrscheinlich habe ich bisher nur Glück gehabt.
Übrigens ist das Problem in anderen DB's gar nicht mal so anders (außer beim SQL-Server).
Eine ReadCommitted-Transaktion, die mal etwas dauert, kann zwischenzeitlich Daten verarbeiten, die von einer anderen Transaktion bereits gelöscht wurden und neue Daten ans Ende angefügt hat. Somit sind die gelöschten noch enthalten und die gerade neu committeten Daten kommen dann dazu. Damit zeigt count(*) mehr an, als tatsächlich noch vorhanden ist.
Allerdings sollte man auch berücksichtigen:
Das Result der lesenden Transaktion ist in sich konsistent.
Bei unserem BI habe wir da auch keinen Synchronisationsprozess, aber einen ETL-Zeitpunkt betroffenen Trigger. Immer dann wenn ein ETL ferig ist, wird der aktuelle Timestamp der Tabelle in einer eigenen Tabelle vermerkt.
Somit kann unser Webserver über diesen Timestamp die Aktualität der Daten prüfen und die Cachedaten (Inmemory-DB) dann neu laden und den Clients zur Verfügung stellen.

Bei klassischen ERP-Systemen ist es allerdings allgemein bekannt, dass die Abfrage, die ich gerade gemacht habe, im Moment der Fertigstellung bereits veraltet sein kann.
Bisher war das in dieser Welt i.Ü. noch nie ein Problem und daher sollte man diese Änderung bzgl. der automatischen ReadConsistency noch mal überdenken.
Bzw. die Möglichkeit dieses abzuschalten auch in V5 zu erhalten.
Denn dieses Verhalten ist keine Spezialität der Firebird sondern aller DBMs.

Außerdem sollte man auch berücksichtigen, dass Daten, die einem User präsentiert werden, im Moment der Anzeige veraltet sein können.
Deshalb wird ja auch z.B. in C# bei der Verwendung eines CommandBuilders der update so gestaltet, dass er den vorherigen Zustand der Zeile komplett überprüft und einen Fehler meldet, wenn die zu ändernden Daten einen anderen Zustand haben als erwartet.
Dies gilt ebenso auch für Batch-Verarbeitungen.

Übrigens: Der SQL-Server hat mit seiner Lock-Escalation das Problem einfach nicht.
Ein Select count(*) oder generell ein Select über eine ganze Tabelle sperrt diese insgesamt vor Veränderungen.
a) Der select wird geparkt, bis alle anderen verändernden Zugriffe commited sind.
b) Der select, wenn er losläuft, sperrt alle verändernden Zugriffe .
Das bremst bei ETL tatsächlich das ganze System aus.

Zurück zu unserem ETL.
Bisher konnten wir da noch keine Probleme mit fehlenden oder zu vielen Daten ermitteln, da der ETL-Prozess insgesamt aus nur einer Transaktion besteht.
vr2
Beiträge: 219
Registriert: Fr 13. Apr 2018, 00:13

bfuerchau hat geschrieben: Sa 12. Aug 2023, 12:25 Wahrscheinlich habe ich bisher nur Glück gehabt.
Übrigens ist das Problem in anderen DB's gar nicht mal so anders (außer beim SQL-Server).
Eine ReadCommitted-Transaktion, die mal etwas dauert, kann zwischenzeitlich Daten verarbeiten, die von einer anderen Transaktion bereits gelöscht wurden und neue Daten ans Ende angefügt hat. Somit sind die gelöschten noch enthalten und die gerade neu committeten Daten kommen dann dazu. Damit zeigt count(*) mehr an, als tatsächlich noch vorhanden ist.
Wenn es sich dabei um ein top-level statement wie select count(*) handelt, ist das sogar laut SQL-Standard falsch. Wir müssen hier aufpassen und differenzieren zwischen Statement und Transaktion. Bei einer ReadCommitted TX mit mehreren Statements soll natürlich jedes Statement den aktuell committeten, möglicherweise jeweils unterschiedlichen Stand sehen. Aber das, was ein einzelnes Statement sieht, muss konsistent sein. Deshalb sprachen die Firebird-Entwickler auch von statement-level consistency. Das illustriert ja mein Test im vorigen Posting. Nun gibt es aber Statements wie select * from my_procedure, wo in der SP mehrere einzelne Statements vorkommen. Und es kann auch sein, dass in der SP autonome oder externe TXen die Daten verändern. Auch da muss eigentlich jedes Statement der SP den jeweiligen bis dahin committeten Stand sehen und das aber auch auf Statement-Ebene konsistent.
Allerdings sollte man auch berücksichtigen:
Das Result der lesenden Transaktion ist in sich konsistent.
Nein, das hat mein Test gezeigt. Wenn 100000 Sätze committet wurden, darf ein Lesestatement nicht Bruchteile davon sehen. Da muss wie sonst auch gelten alles oder nichts.
Bei klassischen ERP-Systemen ist es allerdings allgemein bekannt, dass die Abfrage, die ich gerade gemacht habe, im Moment der Fertigstellung bereits veraltet sein kann.
Bisher war das in dieser Welt i.Ü. noch nie ein Problem und daher sollte man diese Änderung bzgl. der automatischen ReadConsistency noch mal überdenken.
Bzw. die Möglichkeit dieses abzuschalten auch in V5 zu erhalten.
Denn dieses Verhalten ist keine Spezialität der Firebird sondern aller DBMs.
Klar, das ist nicht anders möglich, sonst würde bspw eine Anfrage an ein Buchungssystem mit sehr viel Andrang nie fertig, wenn sie immer nachschauen würde, ob sich vor ihrem Abschluss die Daten geändert haben. ReadConsistency macht in der Hinsicht aber keine Probleme oder irgendwas schlechter als bisher. Und ja, ReadConsistency ist auch bei Firebird 5 schaltbar in firebird.conf, denke, das kommt so bald auch nicht raus. Erst wenn ReadConsistency in Bezug auf Statements in PSQL vollständig geklärt und umgesetzt ist, braucht man den Schalter nicht mehr.
Übrigens: Der SQL-Server hat mit seiner Lock-Escalation das Problem einfach nicht.
Ein Select count(*) oder generell ein Select über eine ganze Tabelle sperrt diese insgesamt vor Veränderungen.
a) Der select wird geparkt, bis alle anderen verändernden Zugriffe commited sind.
b) Der select, wenn er losläuft, sperrt alle verändernden Zugriffe .
Das bremst bei ETL tatsächlich das ganze System aus.
Logisch. Wenn ich den ganzen Laden dichtmache, hab ich natürlich kein Problem mit paralleler Veränderung :D Das entspricht bei Firebird dem Isolation Level "Snapshot Table Stability / Consistency". Das ist in den meisten Fällen viel zu restriktiv. Was man will, ist der aufgabenspezifisch beste Kompromiss zwischen Nebenläufigkeit und Konsistenz, und dass ein Datenbanksystem einem dafür praxistaugliche Alternativen bietet, die der SQL-Standard übrigens auch vorgibt.

Grüße, Volker
bfuerchau
Beiträge: 490
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

Ich denke, dein Test ist nicht ganz koscher.
Du verwendest 10 Inserts hintereinander ohne jedwede Transaktion.
Was macht dann die Default-Transaction deiner Umgebung?
Der NetProvider macht dann eine Standardtransaction ReadCommitted und führt dann automatisch einen Commit am Ende des Statements durch.
Da es auch die Chaos-Transaktion gibt, sind dann natürlich Zwischenergebnisse jederzeit möglich.

Da die Betonung auf Committed liegt, dürfen auch bei dieser einzelnen Transaktion die Daten nicht sichtbar sein.
Packe die 10 Inserts in Einzelaufrufe mit expliziter ReadCommitted-Transaktion und jeweiligen expliziten Commit.
Dann sollte und dürfte dein 2. Thread keine Zwischenergebnisse mehr zeigen.

Beispiel Oracle:
https://docs.oracle.com/cd/B13789_01/se ... onsist.htm
Beispiel DB2 (Isolationlevels incl. Vergleich zu anderen DBMS):

https://datageek.blog/en/2016/06/28/db2 ... phenomena/

Auch hier wird darauf hingewiesen, dass "serializability" ein Performanceproblem darstellt wenn man Statementconsistency erreichen will. Außerdem muss man dies bewusst anwenden.
Diesen Transaktionstyp findet man auch in der Isolationlevel-Auflistung.
https://learn.microsoft.com/en-us/dotne ... ew=net-7.0

Daher würde ich das Aggregatproblem, also nicht nur count(*), ausschließlich an den Isolationlevel hängen und nicht versuchen irgendwas zu automatisieren.
Möchte ich unveränderte Daten dann muss ich halt bewusst eine Snapshot-Transaktion starten.
Ansonsten erhalte ich halt "PhantomReads"
Und im Gegensatz zu den anderen DBMS kann eben die Firebird durch ihre Satzversionen bei Snapshot sehr viel einfacher arbeiten, also ohne Tablelocks, und belasten das DBMS damit nicht zusätzlich, da andere Transaktionen eben nicht ausgeschlossen werden.

Ich habe unseren ETL-Prozess noch mal angesehen.
Wir haben früher den Löschvorgang und den Ladevorgang in getrennte Transaktionen gepackt.
Dies führte zum Ergebnis, dass Dashbaords z.T. dann keine Daten angezeigt hatten.
Mit dem neueren Verfahren (ca. 5 Jahre), wird delete und insert in eine gemeinsame Transaktion gepackt. Dadurch sieht ein Dashboard tatsächlich bis zum commit nur die alten Daten und zwischendurch auch keine Zwischeneregebnisse.
vr2
Beiträge: 219
Registriert: Fr 13. Apr 2018, 00:13

bfuerchau hat geschrieben: So 13. Aug 2023, 11:45 Ich denke, dein Test ist nicht ganz koscher.
Du verwendest 10 Inserts hintereinander ohne jedwede Transaktion.
Nein. Das ist an den Screenshots aber auch nicht zu erkennen, ich hatte es im ersten Post zu dem Test beschrieben. Da hab ich die UDR als eine Art Skriptplayer bezeichnet (das war hier wohl irreführend), aber die UDR kann die Statements auch parallel ausführen, wenn sie entsprechend gekennzeichnet sind.

Jedes Statement, das da steht, wird von der UDR in einer separaten Connection und ReadCommitted-TX ausgeführt. Die äußere TX, die die UDR sequencer aufruft, kann auch eine ReadOnly-TX sein, da sie selber nicht schreibt, sondern nur die Ergebnisse der anderen Connections/TXen ausgibt. Aber das spielt dabei keine Rolle.

Die 10 insert-Statements werden nicht hintereinander, sondern parallel ausgeführt, gleichzeitig, deswegen 10 connections. Es geht darum, dass die commits zeitlich möglichst dicht und häufig genug passieren, damit der Effekt während einer Leseaktion sichtbar wird.

Man braucht keine UDR, um das zu reproduzieren. Wenn Du eine Testanwendung mit .NET o.ä. baust, die auf 10 connections/TXen parallel/gleichzeitig inserts macht, siehst Du den Effekt auch. Erst das select count starten und sofort danach die 10 parallelen inserts.

Grüße, Volker
bfuerchau
Beiträge: 490
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

Bezogen auf meinen ETL-Test kann ich das Problem nicht nachvollziehen.

In der Tabelle ist eine Identity-Column, die beim Insert automatisch vergeben wird um im 2. Lauf einen Änderungseffekt sehen zu können.

Ich halte den ETL-Prozess vor dem Commit an.
Zwischendurch frage ich via IBExpert mittels "select count(*), max(ID)" die Daten ab.
Immer mit Commit und F9. Da ich ca 1.Mio Zeilen lade, habe ich genug Zeit das oft zu wiederholen.
Erst nach dem die Transaktion im ETL committed ist, sind die Daten im IBExpert zu sehen.

Der 2. Lauf macht einen Delete und anschließenden Insert.
Nach dem Delete habe ich angehalten, im IBExpert sind die alten Daten zu sehen.

Auch die letzte ID passt noch. Man merkt allerdings, dass der Count länger läuft, da die nicht committeten Daten überlesen werden müssen.
Nach commit im neuen ETL sind die Daten nun auch in IBExpert zu sehen. Die ID hat sich erwartungsgemäß verdoppelt.
Die Abfrage läuft etwas länger, da die alten Daten überlesen werden müssen.
Aber die Wiederholung ist wieder schnell, da die alten Daten nun als nicht mehr relevant entfernt werden konnten (Minisweep).

Somit kann ich für mich abschließend sagen, dass ReadCommitted in FB3.0 genau das tut, was ich davon erwarte und verlange.

Ich verwende allerdings gezielt EinzelInserts (mit meinem BulkCopy) und keinen "insert ... select".
Vielleicht liegts ja an irgendeiner Implementierung die damit nicht korrekt umgehen kann und ggf. intern "Zwischencommits" produziert. Aber das ist nur Raterei.

Ggf. wird in der "nur Lese-Transaktion" ja kein ReadCommittted verwendet. Mit dem ODBC-Treiber und den NetProvider habe ich die absolut keine Probleme bezogen auf die Transaktionsfehler, der angeblich vorhanden sein soll.
Benutzeravatar
martin.koeditz
Beiträge: 446
Registriert: Sa 31. Mär 2018, 14:35

Hallo bfuerchau,

hast du in IBExpert ggf. noch einen speziellen Isolationsmodus für das Auslesen der Datensätze aktiv? Sonst würde ich dir zustimmen. Macht was es soll.

Gruß
Martin
Martin Köditz
it & synergy GmbH
bfuerchau
Beiträge: 490
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

Ein Bild kann ich leider nicht einfügen (Url?).

Environment-Options => Transaction
Bei allen 3 Einstellungen:
- ReadCommitted

isc_tpb_read_committed
isc_tpb_rec_version
isc_tpb_nowait

Im NetProvider und ODBC-Treiber gibts keine, mir bekannte, Einstellung ohne rec_version zu arbeiten.
Real arbeite ich mit der Einstellung in den ConnectionProperties bei beiden Treibern mit "LOCKTIMEOUT=15;" um bei meiner Sperrlogik nicht ewig zu warten.

Deswegen kann ich die ganze Aufregung um ReadCommitted nicht verstehen. Denn laut SQL-Definition, Link habe ich geposted, ist es korrekt, dass neu committete Daten wähend der Ausführung eben auch sofort sichtbar sind.
Dies nehme ich billigend in Kauf, da das eben normales Verhalten ist.

Nun Frage ich dich:
Welchen Treiber verwendest du?
Ggf. läuft da was falsch mit den Transaktionsoptions.
vr2
Beiträge: 219
Registriert: Fr 13. Apr 2018, 00:13

Deswegen kann ich die ganze Aufregung um ReadCommitted nicht verstehen. Denn laut SQL-Definition, Link habe ich geposted, ist es korrekt, dass neu committete Daten wähend der Ausführung eben auch sofort sichtbar sind.
Dies nehme ich billigend in Kauf, da das eben normales Verhalten ist.

Nun Frage ich dich:
Welchen Treiber verwendest du?
Ggf. läuft da was falsch mit den Transaktionsoptions.
Ich hab doch keinen Vorteil davon, wenn ich hier was poste, was nur ein Phantasieproblem ist. Fest steht, dass der Effekt reproduzierbar ist, und dass er seit 2016 Thema bei den Firebird-Entwicklern ist, und sie die Lösung seit FB4 zum Default gemacht haben. Die haben sicher Besseres zu tun, als eine angeblich fehlerhafte Umsetzung zu korrigieren, die keine ist, und dafür gravierende Nebenwirkungen in Kauf zu nehmen, nämlich, dass PSQL auch bei ReadCommitted-TX wie in einer Snapshot-TX behandelt wird. Ich habe, als ich von dem Problem erfahren habe, auch noch nie Schwierigkeiten deswegen gehabt, das heißt aber nicht, dass es nicht existiert.

Den Link zur SQL-Definition sehe ich nicht.
Treiber? Flamerobin mit fbclient von 4.0.3 oder davor, ist auch egal.
Und es ist egal ob record_version oder no_record_version.

Man kann diesen Effekt nicht manuell mit einem DBA-Tool reproduzieren oder es ist Glückssache. Der tritt am ehesten auf, wenn hohe parallele Last beim insert ist, während gleichzeitig gelesen wird. Wie bei allen Fehlern, die nur bei hoher Nebenläufigkeit halbwegs zuverlässig reproduzierbar sind.

Grüße, Volker
Zuletzt geändert von vr2 am Mo 6. Nov 2023, 02:31, insgesamt 1-mal geändert.
bfuerchau
Beiträge: 490
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

Leider lag ich hier falsch!
Durchstreichen kann man hier leider nicht.

Diese Art der Probleme kenne ich zur Genüge auch in meinen Anwendungen, da diese generell bei Parallelverarbeitung und ggf. hoher Last vorkommen.
Jetzt kann man natürlich den pragmatischen Weg gehen und, weil man den Fehler nicht beheben kann oder findet, einfach eine andere Lösung mit z.T. nicht nachvollziehbaren Konsequenzen einbaut.
Aber Fakt ist doch, dass es ohne Last eben funktioniert!
Somit muss man den Fehler mit Last eben lokalisieren und beheben. Wenn es also nachweislich vorkommt, dass nicht committete Daten in einer ReadCommitted-Transaktion gelesen werden können, so ist doch vorrangig genau dieses Problem zu lösen.
Bei anderen DBMS funktioniert das doch auch.

Das selbe gilt doch auch für Deadlock-Problematiken. In Web-Anwendungen, wo jeder Clientrequest in einem neuen Thread gestartet wird, was durch Ajax-Calls noch forciert werden kann, musste ich auch per Lock-Mechanismen die Prinzipien der Deadlock-Vermeidung strikt anwenden.
Sicherlich hätte ich das, á la Winforms-Queue, über eine sequentielle Queue abarbeiten können, da jeder Web-Call dann per "Invoke" im Hauptthread läuft.
Die Vorteile sind gewaltig:
- Keine Deadlock-Gefahr
- Keine DBMS-Überlastung durch zuviele parallele Abfragen
Beides Probleme, mit denen ich heute halt zu kämpfen habe.
Die Nachteile sind aber gravierender:
- Unzufriedenheit der Kunden
- z.T. sehr lange Antwortzeiten
- Verlust der Kundenakzeptanz
Wobei hier das Hauptproblem in einer Web-Lösung besteht. Mit einer "Fatclient"-Lösung hat halt jeder seine eigene Umgebung, was allerdings in der heutigen Zeit eben nicht mehr zeitgemäß ist.

Da könnte ich ja ebenso gut auf die FB2.5 im Superserver zurückgehen. Je Thread nur eine DB, alle Zugriffe hintereinander.
Aber auch da habe ich dann für Parallelisierungen die FB2.5 als Classicserver verwendet, also je Connection ein Prozess. Und auch da hatte ich bei vielen Clients (noch keine Weblösung) keine Transaktionsprobleme.

Fazit:
Das Problem ist ursächlich zu lösen und nicht nur einfach zu umgehen.

Die Links zu den SQL-Definitionen sind in einem vorherigen Beitrag.
https://firebirdforum.de/viewtopic.php?p=1859#p1859
Zuletzt geändert von bfuerchau am Sa 19. Aug 2023, 16:47, insgesamt 2-mal geändert.
Antworten