Table fireDAC 访问的 SQLite 中的锁

Table locks in SQLite accessed by fireDAC

我正在努力将一组悖论 table 移植到 SQLite。为此,我创建了一个模拟(某种程度上)当前使用场景的测试应用程序:多个用户访问同一个数据库文件并执行同步读写。

该应用程序非常简单:它将启动多个线程,每个线程创建一个连接,打开一个 table 并随机读取、更新或插入 table。

应用程序几乎立即遇到 "database table locked" 错误。我已经尝试了几种方法来尝试解决它,但似乎没有任何效果。我做错了什么?

这是线程内部的代码:

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;

感谢Victoria,我设法找到了正确的参数。

  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');
    Conn.Params.Add('SharedCache=False');
    Conn.Params.Add('LockingMode=Normal');
    Conn.Params.Add('Synchronous=Normal');
    Conn.UpdateOptions.LockWait := True;
    Conn.Open();

再次感谢