【发布时间】:2017-11-02 00:05:20
【问题描述】:
我正在将一组悖论表移植到 SQLite。为此,我创建了一个测试应用程序来模拟(某种程度上)当前的使用场景:多个用户访问同一个数据库文件并同时执行读写操作。
该应用程序非常简单:它将启动多个线程,每个线程创建一个连接,打开一个表并随机读取、更新或插入表内。
几乎立即,应用程序遇到“数据库表锁定”错误。我已经尝试了几件事来尝试解决它,但似乎没有任何效果。我做错了什么?
这是线程内部的代码:
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;
【问题讨论】:
-
在this chapter 你会找到你需要的一切。
-
谢谢,我设法找到了合适的参数。如果你写一个答案,我会接受它。否则,我会自己回答问题。
-
请发表答案。我现在很忙..
标签: sqlite delphi firedac delphi-10.2-tokyo