多个进程同时访问Access数据库中的同一张表。只执行insert操作。
使用TADOQuery连接access,connectionString为:
'Provider=Microsoft.Jet.OLEDB.4.0;Data Source='
    + AMdbName + ';Persist Security Info=False;Mode=ReadWrite|Share Deny None';程序运行中发现偶尔会报:无法更新;当前被锁定 异常。请教高手:
1 access是否支持多进程同时插入?
2 如果支持,那我程序问题在那里?
谢谢!

解决方案 »

  1.   

    mutex和信号量都支持多进程,msdn查一下有例子的
      

  2.   

    改变表肯定要锁的,所以你可以把访问access的事情交给同一个线程干。
      

  3.   

    只执行insert操作的话,需要每个线程用一个单独的ADOConnection来连接数据库,然后就可以几个线程同时插了
      

  4.   

    刚试了下,问题依旧。
    1,2,3楼朋友的意思是:Access本身不支持多个进程同时进行操作。必须我们自己管理进程间的同步,对么?
      

  5.   

    可以用SQL语句来实现,只提交SQL语句应该没有什么问题?
      

  6.   


    请指教,如何用sql语句来实现?
      

  7.   


    ADOQuery1.sql.clear;
    ADOQuery1.SQL.Add('insert into jmdak (编号,姓名,所属社区) values (''9999'',''未输入'',''花园'')');
    ADOQuery1.ExecSQL;
      

  8.   

    现在尝试使用Mutex同步进程。不起作用。调试发现调用CreateMutex创建相同名称的互斥对象。
    不同进程返回的句柄不相同。
    按理说调用CreateMutex如果存在相同名称的互斥对象,则返回此对象的句柄。应该各进程返回的句柄相同。创建互斥对象代码:hmutex:=CreateMutex(nil,false,'mutex001');请高手指教,为啥返回句柄不同?
      

  9.   

    插入部分代码:
    Qry : TADOQuery Qry.ConnectionString:='Provider=Microsoft.Jet.OLEDB.4.0;Data Source='
        + AMdbName + ';Persist Security Info=False;Mode=ReadWrite|Share Deny None';
    with Qry do
    begin
       SQL.Clear;
       SQL.Text := 'insert into rpt_info(fname,rpt) values(:fname,:rpt)';
       Parameters.ParamByName('fname').Value := ARptName;
       Parameters.ParamByName('rpt').LoadFromFile(ARpt, ftBlob);
       EXECSQL;
    end;
      

  10.   


    Qry.ConnectionString:='Provider=Microsoft.Jet.OLEDB.4.0;Data Source='
      + AMdbName + ';Persist Security Info=False;Mode=ReadWrite|Share Deny None';这个语句应该放在线程之外。
      

  11.   

    是多进程这个更应放在线程之外,否则,一个进程就要重新设设置连接一次,每次连接都要时间,虽然很短。多进程更起大放大作用。再者,连接串是固定的,没有必要每次都去改它,所以连接串还是放在线程之外比较合理。
    不知道你的多进程有没有数量限制?,如果有数量最好每个进程配备一个AOD,所有ADO共享一个连接ADOCONNECTION。这样最大可能预防进程之间的调用同一个AOD的冲突。
      

  12.   

    我的多进程是起2个程序,ConnectionString是只连接一次。
      

  13.   

    试了各种可能之后,基本可以确定。access在多个程序同时访问情况下,容易出错。
    考虑进程间同步。但是使用进程间同步后,依然报无法更新错误。我就纳闷了。
    下面是我写了个小列子程序:
    程序循环向表中插入5000个随机数。
    起2个程序同时插入。
    MDB文件存于应用程序目录下,表名:testmp 只包含一个字段:Num(数字)
    虽然使用Mutex同步,依然报无法更新错误。高手帮忙看看啥问题?unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, DB, ADODB;type
      TForm1 = class(TForm)
        Memo1: TMemo;
        Button2: TButton;
        ADOQuery1: TADOQuery;
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure Button2Click(Sender: TObject);
      private
        { Private declarations }
        HMutex:THandle;
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button2Click(Sender: TObject);
    var
      I: Integer;
    begin  for I := 0 to 4999 do
      begin
        if WaitForSingleObject(HMutex,INFINITE) = WAIT_OBJECT_0 then
        begin
          try
            with ADOQuery1 do
            begin
              SQL.Clear;
              SQL.Add('Insert into testmp(Num) values(:Num)');
              Randomize;
              Parameters.ParamByName('Num').Value:=Random(1000);
              Application.ProcessMessages;
              ExecSQL;
              Memo1.Lines.Add(IntToStr(i));
            end;
          except
          on e:exception do
            Memo1.Lines.Add(e.Message)
          end;
        end;
        ReleaseMutex(HMutex);
      end;
      ADOQuery1.Close;
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
      HMutex:=CreateMutex(nil,false,'Mutex007');
      ADOQuery1.ConnectionString:='Provider=Microsoft.Jet.OLEDB.4.0;Data Source='
        + ExtractFilePath(ParamStr(0))+'test.mdb' + ';Persist Security Info=False;Mode=ReadWrite|Share Deny None';
    end;procedure TForm1.FormDestroy(Sender: TObject);
    begin
      CloseHandle(HMutex);
    end;
    end.
      

  14.   

    加了个TAdoConnection。每次插入前打开,完成后关闭。
    这样的话,同步没问题了。procedure TForm1.Button2Click(Sender: TObject);
    var
      I: Integer;
    begin
      Memo1.Lines.Clear;
      for I := 0 to 49999 do
      begin
        if WaitForSingleObject(HMutex,INFINITE) = WAIT_OBJECT_0 then
        begin
          try
            ADOConnection1.Open;
            with ADOQuery1 do
            begin
              SQL.Clear;
              SQL.Add('Insert into testmp(Num) values(:Num)');
              Randomize;
              Parameters.ParamByName('Num').Value:=Random(1000);
              Application.ProcessMessages;
              ExecSQL;
              Memo1.Lines.Add(IntToStr(i));
            end;
            ADOConnection1.Close;
          except
          on e:exception do
          begin
            Label1.Caption:=e.Message;
            Memo1.Lines.Add(e.Message);
          end;
          end;
        end;
        ReleaseMutex(HMutex);
      end;
    end;
      

  15.   

    线程相关我不太懂,但数据处理代码顺序应该改一下.procedure TForm1.Button2Click(Sender: TObject);
    var
      I: Integer;
    begin
      Memo1.Lines.Clear;
     ADOConnection1.Open;//这个放在循环外边  for I := 0 to 49999 do
      begin
        if WaitForSingleObject(HMutex,INFINITE) = WAIT_OBJECT_0 then
        begin
          try
            with ADOQuery1 do
            begin
              SQL.Clear;
              SQL.Add('Insert into testmp(Num) values(:Num)');
              Randomize;
              Parameters.ParamByName('Num').Value:=Random(1000);
              Application.ProcessMessages;
              ExecSQL;
              sleep(30);//给系统一点时间来处理数据,这个时间可调整,具体到多少,我也不确定。数据量越大,数据库处理数据越慢,这个数应该越大。1秒为1000.
              Memo1.Lines.Add(IntToStr(i));
            end;
          except
          on e:exception do
          begin
            Label1.Caption:=e.Message;
            Memo1.Lines.Add(e.Message);
          end;
          end;
        end;
        ReleaseMutex(HMutex);
      end;
        ADOConnection1.Close;//放在循环外边end;
      

  16.   

    每个线程插入数时,都在插入代码外加
    EnterCriticalSection(cs);
    {插入数据到ACESS}
    LeaveCriticalSection(cs);
      

  17.   

    很久的贴子了.看了忍不住挖了..
    CSDN都没几个能分清进程跟线程的不同吗? LZ问的是进程啊. 
    如果是线程随便都处理好了还用问!?