使用多线程缓慢恢复mysql数据库(delphi)

pftdvrlh  于 2021-06-20  发布在  Mysql
关注(0)|答案(1)|浏览(471)

我需要恢复很多mysql数据库备份,我一直在尝试使用多个线程(在delphi中)来加速,每个线程都有自己的连接。当我使用mode_脚本时,我只能每秒处理1个文件(fps),cpu/磁盘/内存完全没有压力
当我使用mode_cmd时,我可以获得高达12+fps的速度,所有内核的cpu都可以达到100%。
使用tclientdataset或子体时,脚本似乎没有使用所有内核,即使使用多个线程也是如此?
最小代码示例:

type
  TWorker = class(TThread)
  private
    FTasks: TThreadStringList;
    FConn: TMyConnection;
    FScript: TMyScript;
    FQ: TMyQuery;
  protected
    procedure Execute; override;
  public
    procedure addTask(const aFn: String);
    constructor create(Suspended: Boolean; const aMyId: LongInt;const aIniDb: TIniDBSettings);
  end;

procedure TWorker.addTask(const aFn: String);
begin
  FTasks.Add(aFn);
end;

constructor TWorker.create(Suspended: Boolean; const aMyId: LongInt; const aIniDb: TIniDBSettings);
begin
  inherited Create(Suspended);
  FTasks := TMTThreadStringList.Create;
  FMyName := 'WORKER__'+IntToStr(aMyId);
end;

procedure TWorker.Execute;
var
  mode: LongInt;
const
    MODE_DOS=1;
    MODE_SCRIPT = 2;
begin  
  FConn := TMyConnection.Create(Nil);
  FConn.Username := aIniDb.iniSDBUsername;
  FConn.Password := aIniDb.iniSDBPass;
  FConn.Database := aIniDb.iniSDBDatabase;
  FConn.Server := aIniDb.iniSDBServer;

  FScript := TMyScript.Create(Nil);
  FScript.Connection := FConn;

    try
        FConn.Connect;
        while not Terminated do begin
          if FTasks.Count > 0 then begin
            tmpFn := FTasks.Strings[0];
            FTasks.Delete(0);

            fMyDbname := 'tmpdb_'+FMyName;

            if(mode=MODE_SCRIPT) then {
                FQ.SQL.Text := 'drop database if exists '+fMyDbname ;
                FQ.Execute;
                FQ.SQL.Text := 'create database '+fMyDbname;
                FQ.Execute;
                FQ.SQL.Text := 'use '+fMyDbname;
                fQ.Execute;
                FScript.SQL.LoadFromFile(tmpFn+'.new');
                FScript.Execute;
            }
            else if(mode=MODE_DOS) then begin
                sCmd := 'cmd.exe /c mysql -u user -h serverip < '+tmpFn;
                GetDosOutput(sCmd,dosOutput);//function using 'CreateProcess()'
            }
            InterlockedIncrement(QDONE);
          end
          else Sleep(15);
        end;
      except on e: Exception do
        MessageBox(0,PWideChar('error'+e.Message),'error',MB_OK);
      end;
    end;
6l7fqoea

6l7fqoea1#

听起来你在用myisam。这是过时的,并且受到“表锁”的影响,这在很大程度上抑制了并行性。
以下与myisam无关:

-SET FOREIGN_KEY_CHECKS=0;
-SET autocommit=0;

与问题相关的一些问题:
你有 AUTO_INCREMENT 柱?
您是否同时从不同的线程插入到同一个表中(myisam和内存有问题,而innodb就没有了。)
有多少 UNIQUE 每张table上的钥匙( INSERTs 由于需要检查DUP而减慢了速度。)
你在用吗 INSERT ? 一次一排?还是成批(一次插入100行的批大约是最佳的——是一次插入1行的10倍。)
还是你在用 LOAD DATA ? (甚至更快。)
“文件”和“表”之间的关系是什么?也就是说,您是将许多小文件加载到一个表中,还是每个文件都是一个表?
raid是否有条带化和/或电池支持的写缓存?
磁盘是hdd还是ssd?
客户端和服务器之间的ping时间是多少(你提到了“网络”,但没有表示接近。)
有多少张table?是否每秒最多创建1.87个表?三个文件要写,一个文件要读(windows在快速打开文件方面不是最好的。)这大约是每秒打开7个文件(注意:如果使用innodb,则每个表只需要1个文件 innodb_file_per_table=1 .)
请提供 SHOW CREATE TABLE 为了几张更大的table。请提供所用sql语句的示例。
威尔逊的要求也很方便。

相关问题