Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Firebird:deadlock - update conflicts with concurrent update (https://www.delphipraxis.net/63039-firebird-deadlock-update-conflicts-concurrent-update.html)

Jasocul 13. Feb 2006 13:27

Re: Firebird:deadlock - update conflicts with concurrent upd
 
Zitat:

Zitat von Hansa
@Jasocul : wie kann ich denn leicht feststellen, ob sich ein Datensatz während der Bearbeitung von woanders her geändert hat ? Vor allem : woher weiß ich, was sich genau geändert hat um gezielt darauf zu reagieren ?

Zitat:

Zitat von Jasocul
Datensatz einlesen und nicht locken (Keine DB-sensitiven Felder verwenden!).
Jetzigen DS-Inhalt merken.
Änderungen durchführen (Off-Line).
Den Datensatz aktuell nochmal holen und vergleichen, ob er sich geändert hat.
Hat sich geändert -> Daten können nicht geschrieben werden, da DS sich geändert hat.
Keine Änderung -> eigene Änderungen können gespeichert werden.

@Hansa:
Nicht immer nur einen Teil lesen. :zwinker:

Gruber_Hans_12345 13. Feb 2006 13:53

Re: Firebird:deadlock - update conflicts with concurrent upd
 
So, hab mich mit den Infos noch etwas dahintergehängt, und nun folgendes zusammengestellt :

In meiner Transaction verwende ich nun folgendes als Parameter

SQL-Code:
read_committed
wait
nun verhält sich das ganze so, wie ich es möchte .... hoffe das hat keine negativen seiteneffekte

Hansa 13. Feb 2006 17:41

Re: Firebird:deadlock - update conflicts with concurrent upd
 
Echt lustig, zu lesen, daß es mit dem Lesen angeblich nichts zu tun hat und read_committed den Fehler beseitigt. 8) Da sage ich nur : zu zwangsläufigen Nebenwirkungen fragen sie ihren Apotheker. :lol: Ich bleibe dabei : schreibende Ttransaktionen möglichst kurz halten und die lesende abtrennen.

Zitat:

Zitat von Jasocul
Den Datensatz aktuell nochmal holen und vergleichen, ob er sich geändert hat.

Hat sich geändert -> Daten können nicht geschrieben werden, da DS sich geändert hat.

Keine Änderung -> eigene Änderungen können gespeichert werden.

[/quote]

Das ist etwas zu kurz. Wenn, dann läufts so ab : lesende Transaktion mit Commit. Der Datensatz kann dann solange offen bleiben, wie er will. Aber bevor er endgültig abgespeichert wird : Lock und neu lesen. Neu gelesenen und den vorhandenen vergleichen. Dann weiter wie Du sagst : keine Änderung : speichern, Lock aufheben.

Meine Frage zielte aber darauf hinaus einfach zu erkennen, ob ein Datensatz zwischenzeitlich doch geändert (womöglich sogar gelöscht) wurde. Was wurde wo geändert ? Speziell welche Felder sind betroffen ? Und wie darauf reagieren ? Wurden umfangreiche Änderungen von 2 Leuten durchgeführt, dann wäre es eventuell sogar sinnvoll, gezielt einen neuen Datensatz aus den 2 geänderten zusammenzubauen, bevor komplett alles über den Haufen geworfen wird. IB/FB besitzt einen BDR (Back Difference Record). Vermutlich ist der für sowas gedacht. Aber keiner weiß wie.

Gruber_Hans_12345 13. Feb 2006 17:50

Re: Firebird:deadlock - update conflicts with concurrent upd
 
Zitat:

Zitat von Hansa
Echt lustig, zu lesen, daß es mit dem Lesen angeblich nichts zu tun hat und read_committed den Fehler beseitigt. 8) Da sage ich nur : zu zwangsläufigen Nebenwirkungen fragen sie ihren Apotheker. :lol: Ich bleibe dabei : schreibende Ttransaktionen möglichst kurz halten und die lesende abtrennen.

Ich kann dir mein Beispielprogramm zeigen, damit mal klar ist was ich genau meine :

Delphi-Quellcode:
function TMyDataBase.OpenSQL(sqlCmd : string = '') : TIBQuery;
begin
    Result             := TIBQuery.Create(nil);
    FLastSQL           := Result;
    Result.DataBase    := FDB;
    Result.Transaction := TIBTransaction.Create(nil);
    Result.Transaction.Params.Add('read_committed');
    Result.Transaction.Params.Add('wait');
    Result.Transaction.DefaultDatabase := Result.DataBase;
    Result.Transaction.StartTransaction;
    if length(sqlCmd) > 0 then Result.SQL.Text := sqlCmd;
end;

// CloseSQL macht nur ein Commit in der Transaktion und gibt alles wieder frei
// ConnectDB verbindet sich zum Firebird Server


procedure TForm1.Button1Click(Sender: TObject);
begin
    D.ConnectDB('192.168.2.250:d:\interbase\data.fdb', 'SYSDBA', 'masterkey');
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
    R.ConnectDB('192.168.2.250:d:\interbase\data.fdb', 'SYSDBA', 'masterkey');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
    sql1                := D.OpenSQL;
    sql1.SQL.Text  := 'UPDATE TEMP SET BEZEICHNUNG = ''TEST'' WHERE ID = 9';
    sql1.ExecSQL;
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
    sql2                := R.OpenSQL;
    sql2.SQL.Text  := 'UPDATE TEMP SET STATUS = 9 WHERE ID = 9';
    sql2.ExecSQL;
end;

procedure TForm1.Button5Click(Sender: TObject);
begin
    D.CloseSQL(sql1);
end;

procedure TForm1.Button6Click(Sender: TObject);
begin
    R.CloseSQL(sql2);
end;
Programm zwei mal starten :

im ersten Programm
*) Button1 Clicken (Datenbankverbindung herstellen)
*) Button2 Clicken (Transaction aufbauen und UPDATE)

im zweiten PRogramm
*) Button1 Clicken (Datenbankverbindung herstellen)
*) Button2 Clicken (Transaction aufbauen und UPDATE)
*) Diese Programm hängt nun (und wartet auf das COMMIT oder ROLLBACK im ersten Programm)

im ersten Programm nun Button3 -> COMMIT

*) mit Standardeinstellungen kommt im zweiten Programm der obige Deadlock Fehler
*) mit den obigen Eisntellungen, wird das UPDATE richtig ausgeführt (es steht anschließend TEST und als Status 9 in der DB)



Also: Es gibt hier keine reine Lesende Transaktion.
Die schreibende kurzhalten ist schon klar, habe ich immmer versuchtm und werde ich auch, aber wenn viele User gleichzeitig arbeiten dann passiert es trotzdem zwangsläufig ....


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

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