Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Lock conflict on no wait transaction ? (https://www.delphipraxis.net/158881-lock-conflict-no-wait-transaction.html)

Hansa 6. Mär 2011 17:29

Datenbank: Firebird • Version: 2.X • Zugriff über: FibPlus

Lock conflict on no wait transaction ?
 
Hi,

ich will mit dieser Prozedur gleichzeitige Zugriffe im Netzwerk simulieren :

Delphi-Quellcode:
procedure TForm1.WriteData (Nr : integer;bez : string);
begin
  DS.Close;
  DS.SelectSQL.Text := 'SELECT * FROM TESTTABLE WHERE NR='+IntToStr (Nr);
  DS.Open;
  if not DS.IsEmpty then begin
    DS.Edit;
    DS.FieldByName('NR').AsInteger := Nr;
    DS.FieldByName('BEZ').AsString := 'Edit ' + bez;
  end
  else begin
    DS.Insert;
    DS.FieldByName('NR').AsInteger := Nr;
    DS.FieldByName('BEZ').AsString := 'Ins ert ' + bez;
  end;
  DS.Post;
end;

procedure TForm1.btn1Click(Sender: TObject);
var i,j : Integer;
    anfang : TTime;
begin
  anfang := now;
  DB.Open;
  Randomize;
  for i := 1 to 2000 do begin
    j := Random (2);
    WriteData (j,IntToStr(10 * i));
    mem1.Lines.Add(IntToStr(i) + ' Diff. : '+ TimeToStr(now-anfang)+' '+IntToStr (j));
  end;
  WriteTransaction.Commit;
end;
Durch das Random (2) ist ja klar, dass es irgendwo bald krachen wird. Soll es ja auch. Nach kurzer Zeit kommt (sofern das Programm mehrfach gestartet wird) dann auch dieser Fehler :

Zitat:

EFIBInterBaseError. Meldung: 'Form1.DS.UpdateQuery:
Unsuccessful execution caused by system error that does not preclude successful execution of subsequent statements.
Lock conflict on no wait transaction.
Deadlock.
Update conflicts with concurrent update.
Ich habe 2 Transaktionen mit diesen Parametern :

TRParams (ReadTransaction) :

read
nowait
read_committed
rec_version


TRParams (WriteTransaction) :

write
nowait
concurrency

Bei Database ist ReadTransaction las DefaultTransaction und WriteTransaction als DefaultUpdateTransaction gesetzt.

Dann noch das Dataset DS. AutoCommit steht auf true. Transaction : ReadTransaction. UpdateTransAction : WriteTransaction.

Jetzt die Frage : wie behandelt man solche Fehler jetzt am besten ? Solche Fehler werden im Realeinsatz zwar eher selten auftreten, behandeln muss man sie aber trotzdem. Wie machen das andere? Sollte man die Transaction-Parameter vielleicht anders setzen ?

mkinzler 6. Mär 2011 18:26

AW: Lock conflict on no wait transaction ?
 
Wann startest du duie Transaktion(en)?

Hansa 6. Mär 2011 18:42

AW: Lock conflict on no wait transaction ?
 
Momentan sind sie im OI auf true gesetzt.

hoika 6. Mär 2011 19:51

AW: Lock conflict on no wait transaction ?
 
Hallo,

Update conflicts with concurrent update.

Du selbst als Programmierer musst den Konflikt lösen.
Eine der beiden Transaktionen muss ein RollBack machen.


Heiko

jobo 6. Mär 2011 20:02

AW: Lock conflict on no wait transaction ?
 
Was willst Du denn eigentlich mit den Transaktionen erreichen?
Vielleicht könntest Du ja ohne auskommen?

mkinzler 6. Mär 2011 20:13

AW: Lock conflict on no wait transaction ?
 
Enteder autocommit oder explizit, aber nicht mischen

jobo 6. Mär 2011 20:19

AW: Lock conflict on no wait transaction ?
 
Ich bin für explizit weglassen. :)

Hansa 6. Mär 2011 20:33

AW: Lock conflict on no wait transaction ?
 
Äh, was weglassen ? Ganz ohne Transaktionen oder wie ? :shock: Mit Firebird ? :P

Momentaner Stand ist jetzt so (Autocommit = false) :
Delphi-Quellcode:
procedure TForm1.btn1Click(Sender: TObject);
var i,j : Integer;
    anfang : TTime;
    answer : TModalResult;
begin
  anfang := now;
  Randomize;
  for i := 1 to 2000 do begin
    answer := idYes;
    j := Random (25);
    mem1.Lines.Add(IntToStr(i));
    repeat
      if not DB.Connected then
        DB.Open;
      if not WriteTransaction.InTransaction then
        WriteTransaction.StartTransaction;
      if not ReadTransaction.InTransaction then
        ReadTransaction.StartTransaction;
      try
        if DebugHook <> 0 then
          WriteData (j,'IDE '+ IntToStr(10 * i))
        else
          WriteData (j,IntToStr(10 * i));
        if WriteTransaction.InTransaction then
          WriteTransaction.Commit;
        if ReadTransaction.InTransaction then
          ReadTransaction.Commit;
      except
        answer := MessageBox(Self.Handle,'Wiederholen ?','Information',MB_ICONINFORMATION or MB_YESNO);
      end;
    until (Answer = idYes) or (Answer = idNo);
    if Answer = idNo then
      Break;
  end;
  mem1.Lines.Add(IntToStr(i) + ' Diff. : '+ TimeToStr(now-anfang)+' '+IntToStr (j));
end;
Was ist davon zu halten ? Sieht so aus, als würde das so laufen. Allerdings weiss ich nicht genau was da geschrieben wird, sofern "Wiederholen" gedrückt wird. :mrgreen:

Blup 7. Mär 2011 09:10

AW: Lock conflict on no wait transaction ?
 
"Lock conflict" kann man auch schon zu Begin der Bearbeitung auslösen:

> Benutzer will Objekt bearbeiten
> Dummy-Update auf Objekt

Fall1: Lock conflict
> Rollback
> Meldung an Benutzer
> Ende

Fall2: Objekt ist jetzt für andere Benutzer gesperrt.
> eventuell zusätzlich oder aktualisierte Daten lesen
> Änderungen vornehmen und Posten
> Commit
> Ende

jobo 7. Mär 2011 17:20

AW: Lock conflict on no wait transaction ?
 
Zitat:

Zitat von Hansa (Beitrag 1086307)
Äh, was weglassen ? Ganz ohne Transaktionen oder wie ? :shock: Mit Firebird ? :P

Ganz weglassen natürlich nicht, Transaktionen entstehen ja von allein. Ich meinte natürlich explizites Transaktionshandling im Client, das sollte man (auch in Firebird?!) weglassen können.
Es sei denn, ja weiß ich auch nicht. :)

Hansa 7. Mär 2011 18:13

AW: Lock conflict on no wait transaction ?
 
Jobo, es geht nicht um die Tatsache, dass es Transaktionen gibt. UNd ja, man kann die nicht weglassen. Eine DB braucht eine Transaction und ein Dataset auch usw. und basta. Die "erfinden" sich nicht von alleine eine Transaktion ! :shock:

Das hier ist allerdings noch wichtig :

Zitat:

Zitat von Blup (Beitrag 1086382)
Fall2: Objekt ist jetzt für andere Benutzer gesperrt.
> eventuell zusätzlich oder aktualisierte Daten lesen
> Änderungen vornehmen und Posten
> Commit
> Ende

Vor allem das mit den "aktualisierte Daten lesen". Du meinst ja ungefähr so, oder ?
Delphi-Quellcode:
  DS.Close;
  DS.SelectSQL.Text := 'SELECT * FROM TESTTABLE WHERE NR='+IntToStr (Nr);
  DS.Open;
  if not DS.IsEmpty then begin
    DS.Edit;
//   neu Lesen, wie weiter ????????
Mit 2. Dataset oder wie ? Mir wäre fast folgendes am liebsten. 3 Datasets. Erstens das Original, zweitens das, was gerade bearbeitet wird. Und dann noch vor dem endgültigen speichern ein neu gelesenes. Dann könnte man nämlich auch eventuell doch zwischenzeitlich gemachte Änderungen behandeln. Nur, wie am besten machen ?

mkinzler 7. Mär 2011 21:25

AW: Lock conflict on no wait transaction ?
 
Wegen der verwendeten Versionierung, sind Transaktionen in Firebird unabdingbar ( Alles läuft in Transaktionen)

jobo 7. Mär 2011 22:05

AW: Lock conflict on no wait transaction ?
 
Welche Versionierung?
Ich kenne mich mit Firebird nicht aus.
Gibt es da besondere Anforderungen oder Gründe für Transaktionen auf Clientseite?

Hansa 7. Mär 2011 22:37

AW: Lock conflict on no wait transaction ?
 
Zitat:

Zitat von jobo (Beitrag 1086659)
Welche Versionierung?

Wer nicht mal das weiss, für den ist klar :

Zitat:

Zitat von jobo (Beitrag 1086659)
Ich kenne mich mit Firebird nicht aus.

Soll jetzt hier etwa einer die absoluten Grundlagen erklären ? In einem Thema, wo es um Mehrplatzsysteme geht oder wie ? Oder wird "lediglich nur" gespammt ?

mkinzler 8. Mär 2011 05:33

AW: Lock conflict on no wait transaction ?
 
Firebird verwendet keinen Transaktionslog, wie andere DBMS, sondern Datensatzversionierung. Bei einem Update eines DS wird eine neuer DS mit höherer Version erzeugt. Andere Transaktionskontexte sehen aber noch den alten DS. Deshalb müssen auch Selects in Transaktionen laufen, um die richtige Version zu bekommen.

Hansa: Nach Gespamme sehen seine Antworten gar nicht aus.

jobo 8. Mär 2011 06:58

AW: Lock conflict on no wait transaction ?
 
@markus: Danke, aber ich habe den Clou glaube ich noch nicht ganz verstanden. Geht es um Isolation Level?

Sorry Hansa, dass ich mich ohne tief greifende Firebird Kenntnisse in die Diskussion eingemischt hab.
In meiner Datenbank-Welt ist es immer so, dass ich mich darauf verlasse/ die Datenbank mir garantiert, dass nur ich in meiner Transaktion die geänderten Daten sehe und niemand anders. Wie das garantiert wird, ist mir dabei erstmal egal.

Was die "absoluten Grundlagen" angeht, die werden doch hier täglich vermittelt, oder?

Im übrigen gefällt mir das Forum, weil man hier nicht angemacht wird, wegen des Frageniveaus.

mkinzler 8. Mär 2011 07:02

AW: Lock conflict on no wait transaction ?
 
Zitat:

@markus: Danke, aber ich habe den Clou glaube ich noch nicht ganz verstanden. Geht es um Isolation Level?
Nein, obwohl dieses damit zusammenhängt.

Es hat damit zu tun, wie der Firebird-Server Transaktionen/Änderungen innerhalb von Transaktionen verwaltet. Die meissten DBMS verwenden hierfür eine Logdatei, in der die Änderungen protokolliet werden; beim Rollback werden dieses dann in umgekehrter Reihenfolge umgekehrt.
Firebird verwendet hier für Versionierung, d.h. es wird beim Update der vorhandene Datensatz nicht geändert, sondern ein neuer mit einer höheren Version erzeugt. Das DBMS verwaltet diese Versionen und welche Version welcher Transaktionskontext sieht. Beim Rollback wird dann nur die Version des Kontext ungültig.

jobo 8. Mär 2011 07:40

AW: Lock conflict on no wait transaction ?
 
OT:
Mmh, wie gesagt, ich verstehs nicht und es scheint mir um die Technik hinter einer Transaktion zu gehen.
Ich versteh auch nicht, wieso man um ein einziges Insert oder Update eine Clienttransaktion baut.
Aber das ist ja nicht mein Thread.

Lemmy 8. Mär 2011 08:00

AW: Lock conflict on no wait transaction ?
 
Hi,

ganz einfach: weil da ne Menge schief gehen kann. Vergiss nicht, dass selbst durch ein einfaches Insert ne ganze Menge an Tabellen betroffen sein können (Triggers usw.).

Weiterhin: Wäre doch auch schlecht für dein Bankkonto, wenn die Bank für kleine Überweisungen unter 50€ auch keine Transaktionen einsetzen würde ;-)

Grüße


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:38 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