Ich arbeite an der Portierung einer Reihe von Paradox-Tabellen zu SQLite. Um dies zu tun, habe ich eine Testanwendung erstellt, die (etwas) das aktuelle Nutzungsszenario simuliert: mehrere Benutzer, die auf die gleiche DB-Datei zugreifen und simultane Lese- und Schreibvorgänge ausführen.Tabellensperren in SQLite, auf die von FireDAC zugegriffen wird
Die Anwendung ist sehr einfach: Es startet mehrere Threads, die jeweils eine Verbindung erstellen, öffnet eine Tabelle und wird nach dem Zufallsprinzip zu lesen, zu aktualisieren oder in die Tabelle einfügen.
Fast sofort, Die Anwendung entdeckt einen Fehler "Datenbank Tabelle gesperrt". Ich habe versucht, einige Dinge zu versuchen, um es zu umgehen, aber nichts scheint zu funktionieren. Was mache ich falsch ?
Hier ist der Code intern auf die Gewinde:
procedure testDB(TargetFolder: string);
var
Conn: TFDConnection;
Table: TFDTable;
i: Integer;
begin
randomize;
Conn := TFDConnection.Create(nil);
try
Conn.DriverName := 'SQLite';
Conn.LoginPrompt := false;
Conn.Params.clear;
Conn.Params.Database := TPath.Combine(TargetFolder, 'testDB.sdb');
Conn.Params.Add('DriverID=SQLite');
// all this is the result of several attemp to fix the table locking error. none worked
Conn.Params.Add('LockingMode=Normal');
Conn.Params.Add('Synchronous=Normal');
Conn.UpdateOptions.UpdateMode := TUpdateMode.upWhereAll;
Conn.UpdateOptions.LockWait := True;
Conn.UpdateOptions.LockMode := TFDLockMode.lmPessimistic;
Conn.UpdateOptions.LockPoint := TFDLockPoint.lpImmediate;
Conn.UpdateOptions.AssignedValues := [uvLockMode,uvLockPoint,uvLockWait];
Conn.Open();
Conn.ExecSQL('CREATE TABLE IF NOT EXISTS ''test'' (''ID'' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,''data1'' TEXT NOT NULL,''data2'' INTEGER NOT NULL)');
Table := TFDTable.Create(nil);
try
table.Connection := Conn;
while True do
begin
case Trunc(Random(10)) of
0..3:
begin
table.Open('test');
try
if table.Locate('data1', 'name'+intToStr(Trunc(Random(10))),[TLocateOption.loCaseInsensitive]) then
begin
table.Edit;
table.FieldByName('data2').AsInteger := table.FieldByName('data2').AsInteger + 1;
table.Post;
end;
finally
table.close;
end;
end;
4..8:
begin
table.Open('test');
try
i := Trunc(Random(10));
if not table.Locate('data1', 'name'+ i.ToString,[TLocateOption.loCaseInsensitive]) then
begin
table.AppendRecord([null, 'name'+ i.ToString, 0]);
end;
finally
table.close;
end;
end
else
break;
end;
end;
finally
FreeAndNil(Table);
end;
finally
FreeAndNil(Conn);
end;
end;
In [dieses Kapitel] (http://docwiki.embarcadero.com/RADStudio/en/Using_SQLite_with_FireDAC#SQLite_Transactions.2C_Locking.2C_Threads_and_Cursors) finden Sie alle finden, die Sie benötigen. – Victoria
Danke, ich habe es geschafft, die richtigen Parameter zu finden. Wenn Sie eine Antwort schreiben, werde ich es akzeptieren. Ansonsten beantworte ich die Frage selbst. – Stephane
Geben Sie bitte eine Antwort ein. Ich bin jetzt ziemlich beschäftigt. – Victoria