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.
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 ....