Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi InterBase: lock conflict on no wait transaction violation of FOREIGN KEY constraint (https://www.delphipraxis.net/192495-interbase-lock-conflict-no-wait-transaction-violation-foreign-key-constraint.html)

mjustin 24. Apr 2017 10:13

Datenbank: InterBase • Version: 7.5.1 • Zugriff über: dbExpress

InterBase: lock conflict on no wait transaction violation of FOREIGN KEY constraint
 
Phänomen:

in eine 'Detail'-Tabelle wird per dynamisch erzeugtem SQL ein INSERT durchgeführt, der Primary Key wird über GEN_ID erzeugt, als Foreign-Key wird ein bestehender PK der Master-Tabelle eingefügt. Die dynamische Query wird über eine neu erzeugte TSQLQuery Instanz ausgeführt.

Ab und zu schlägt das INSERT fehl mit der Meldung:
Code:
lock conflict on no wait transaction violation of FOREIGN KEY constraint "CONSTRAINT_FK" on table "DETAIL".
Die Constraint CONSTRAINT_FK ist definiert als
Code:
FOREIGN KEY (FK_MASTER) REFERENCES MASTER (PK) ON DELETE CASCADE
Dass ein INSERT mit einer "violation of FOREIGN KEY" fehlschlägt, obwohl der dabei verwendete FK existiert, ist schon eigenartig. In einem Screenshot der Anwendung ist der Master-Datensatz in einem DBGrid sichtbar.

Natürlich kann der Master-Datensatz gleichzeitig in anderen Transaktionen angezeigt und editiert werden, jedoch ändert sich sein PK dabei nicht.

alex517 24. Apr 2017 10:56

AW: InterBase: lock conflict on no wait transaction violation of FOREIGN KEY constrai
 
Wird der Master-Datensatz innerhalb der selben Transaktion wie der Detail-Datensatz geschrieben?
Wenn nicht, ist der Master-Datensatz bereits durch ein Commit bestätigt?

mjustin 24. Apr 2017 11:03

AW: InterBase: lock conflict on no wait transaction violation of FOREIGN KEY constrai
 
Zitat:

Zitat von alex517 (Beitrag 1368820)
Wird der Master-Datensatz innerhalb der selben Transaktion wie der Detail-Datensatz geschrieben?
Wenn nicht, ist der Master-Datensatz bereits durch ein Commit bestätigt?

Die INSERTS sind in verschiedenen Transaktionen, der MASTER wird zeitlich lange vor dem DETAIL erzeugt und comitted. Der Client sieht den Master (z.B. wird er in einem DBGrid selektiert), der Benutzer startet per Knopfdruck das Detail-Insert. (Leere / Null FK Werte werden abgefangen). Isolationslevel ist READ COMITTED.

alex517 24. Apr 2017 11:32

AW: InterBase: lock conflict on no wait transaction violation of FOREIGN KEY constrai
 
Der Isolationslevel wäre meine nächste Frage gewesen.
Wenn alles so zutrifft wie du es beschreibst, dürfte der FK-Fehler nicht auftreten.

Ich würde prüfen, ob die von mir gemachten Annahmen auch immer so zutreffen.
z.B.

Ist das Commit wirklich gemacht worden?

Hat Firebird vllt. doch Recht und die einzutragende Master-ID gibt es unter
bestimmten Umständen doch nicht oder nicht mehr?

Stimmt der Isolationslevel?

Suche ich die Ursache an der richtigen Stelle?

jobo 24. Apr 2017 11:35

AW: InterBase: lock conflict on no wait transaction violation of FOREIGN KEY constrai
 
Was ich da irritierend finde ein "Lock" conflict bei insert.
1. Das kann vorkommen, wenn die DB kein Row Level Locking kann.
Weiß nicht, wie das da bei IB und genau dieser Version aussieht.

2. Die zugehörige Fehlermeldung (seitens Firebird) spricht in der Erläuterung von Updates oder Deletes, nicht von Inserts.

Daraus ergibt sich die Frage, fliegen hier nebenläufig noch andere Anweisungen rum?
Ist das "dynamisch" generierte Statement tatsächlich korrekt? (Werden die ID verwendet (Master), die auch gewünscht sind?
Oder bestehen beim Master oder Detail Tabelle andere Abhängigkeiten in Form von Triggern oder cascading constraints, die zu diesem Problem führen (bspw. Selbstreferenz, ...)

(Quelle http://www.firebirdfaq.org/faq109/ -hab mir nicht die Mühe gemacht, nach original IB Doku zu suchen, ist also vielleicht irreführend, was da steht)

P.S.: Der Isolation level sollte m.E. ok sein.

mjustin 24. Apr 2017 12:05

AW: InterBase: lock conflict on no wait transaction violation of FOREIGN KEY constrai
 
Zitat:

Zitat von jobo (Beitrag 1368839)
Daraus ergibt sich die Frage, fliegen hier nebenläufig noch andere Anweisungen rum?
Ist das "dynamisch" generierte Statement tatsächlich korrekt? (Werden die ID verwendet (Master), die auch gewünscht sind?
Oder bestehen beim Master oder Detail Tabelle andere Abhängigkeiten in Form von Triggern oder cascading constraints, die zu diesem Problem führen (bspw. Selbstreferenz, ...)

(Quelle http://www.firebirdfaq.org/faq109/ -hab mir nicht die Mühe gemacht, nach original IB Doku zu suchen, ist also vielleicht irreführend, was da steht)

P.S.: Der Isolation level sollte m.E. ok sein.

Da multi-user, fliegen einige andere Anweisungen rum. Die sind in anderen Prozessen, im aktuelle Prozess laufen keine Threads o.ä. mit Datenbankzugriff. Als weitere Absicherung prüft das Programm vor dem INSERT, ob der als FK einzutragende Wert tatsächlich in der MASTER Tabelle "sichtbar" ist (existiert).
In 99,9 Prozent aller Fälle funktioniert das INSERT. Einen Fehler im Statement kann ich daher beherzt ausschliessen.

Es gibt nur einen Trigger (BEFORE INSERT) in der Detail-Tabelle. Er sorgt für einen vorhandene Primary Key in der Detail-Tabelle, und füllt ein Feld mit dem aktuellen Usernamen der Connection.

if (new.detail_pk is null) then
new.detail_pk = gen_id(gen_detail, 1);

if (new.DB_USER_NAME is null) then
new.DB_USER_NAME = user;

Da das Problem nur selten auftritt, halte ich es für wahrscheinlich dass Aktionen die in einer anderen Transaktion durchgeführt werden - z.B. der MASTER Datensatz wurde in einer anderen Transaktion geändert, aber noch nicht comitted - verantwortlich sind. Ich schaue mal ob ich etwas reproduzierbares finde.

mjustin 24. Apr 2017 12:19

AW: InterBase: lock conflict on no wait transaction violation of FOREIGN KEY constrai
 
Zitat:

Zitat von jobo (Beitrag 1368839)
Daraus ergibt sich die Frage, fliegen hier nebenläufig noch andere Anweisungen rum?

Also so etwas :)

Es ist reproduzierbar:

* ich starte in einem Datenbankclient eine Transaktion, ändere einen Wert (natürlich nicht den PK!) im Master, aber führe kein COMMIT durch
* ich führe im Programm (andere Transaktion) das INSERT in der Detail-Tabelle aus
* und: die Fehlermeldung erscheint

Schlussfolgerung: Detail-INSERTs sind nur bei geschlossenen Transaktionen auf den MASTER möglich. Nächste Frage ist, ob das immer, nicht nur bei diesem Tabellenpaar auftritt...

jobo 24. Apr 2017 12:28

AW: InterBase: lock conflict on no wait transaction violation of FOREIGN KEY constrai
 
Macht Ihr denn da im Programm explizite Transaktionsanweisungen?
Also Connection.BeginTrans oder irgendsowas- weiß nicht mehr wie das da genau genannt wird?
Die Frage wäre auch glaub ich nicht so sehr, was geändert wird, sondern ab welchem Moment die Sperre gesetzt wird und ob es nur eine Schreibsperre oder sogar eben Lesesperre wäre (das Insert verlangt ja per Definition durch FK Constraint nur die Existenz des Mastersatzes).
Also macht Ihr explizit was per Code beim Ändern des Masters oder wenn nicht, welche Sperren setzt der Server und wann genau.

Mit "rumfliegen" meinte ich zunächst nur in der gleichen Sitzung (nicht unbedingt Transaktion). Wenn Ihr fachbedingt Änderung an gleichen Datensätzen aus unterschiedlichen Sitzungen vornehmt, muss man sich das natürlich alles genauer ansehen.
Oder entsteht das (Phänomen) nur, weil ggF. ein User das Programm mehrfach laufen hat und mit mehreren Intanzen des Programms am gleichen Fall arbeitet?

Ps.: Achso, Du machst die Änderung im gleichen Programm/Sitzung?

mjustin 24. Apr 2017 12:33

AW: InterBase: lock conflict on no wait transaction violation of FOREIGN KEY constrai
 
Zitat:

Zitat von jobo (Beitrag 1368859)
Macht Ihr denn da im Programm explizite Transaktionsanweisungen?

Nein, wir verwenden die Default-Transaktionen die von dbExpress verwaltet werden.

Mit einem anderen SQL Tool (IBExpert) habe ich das ganze reproduziert, sowohl im konkreten Master-Detail Tabellenpaar das die Fehlermeldung erzeugte, als auch in einem ähnlichen Master-Detail Paar. Das Verhalten tritt dort auch auf. In IBExpert habe ich dazu zwei SQL Editor Fenster geöffnet, d.h. UPDATE aus Master und INSERT in Detail erfolgen in verschiedenen Transaktionen.

Nun wage ich zu folgern (zumindest für InterBase 7.5):

INSERTs in eine Detailtabelle, die per Foreign-Key Constraint mit einer Mastertabelle verknüpft sind, schlagen fehl, wenn am Mastersatz Änderungen gemacht wurden, für die noch kein COMMIT erfolgte

alex517 24. Apr 2017 12:46

AW: InterBase: lock conflict on no wait transaction violation of FOREIGN KEY constrai
 
Zitat:

Zitat von mjustin (Beitrag 1368861)
Nun wage ich zu folgern (zumindest für InterBase 7.5):

INSERTs in eine Detailtabelle, die per Foreign-Key Constraint mit einer Mastertabelle verknüpft sind, schlagen fehl, wenn am Mastersatz Änderungen gemacht wurden, für die noch kein COMMIT erfolgte

Das muss so sein (ist auch schon immer so),
sonst könntest du dein Detail nicht committen,
da der Master ja mit Rollback wieder verworfen werden könnte.


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:12 Uhr.
Seite 1 von 2  1 2      

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