медленное восстановление базы данных mysql с несколькими потоками (delphi) - PullRequest
0 голосов
/ 03 июля 2018

Мне нужно восстановить множество резервных копий базы данных mysql, и я пытаюсь ускорить работу, используя несколько потоков (в Delphi), каждый из которых имеет собственное соединение. Когда я использую MODE_SCRIPT, я могу обрабатывать только около 1 файла в секунду (fps), при этом CPU / DISK / MEMORY вообще не нагружены

Когда я использую MODE_CMD, я могу достигать 12 + fps с процессором до 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;

1 Ответ

0 голосов
/ 04 июля 2018

Звучит так, как будто вы используете MyISAM. Это устарело и страдает от «блокировок таблиц», что сильно тормозит параллелизм.

Следующие значения не имеют отношения к MyISAM:

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

Некоторые вопросы, связанные с проблемой:

  • Есть ли у вас AUTO_INCREMENT столбцы?
  • Вы вставляете в одну и ту же таблицу одновременно из разных потоков? (Проблематично с MyISAM и MEMORY, меньше с InnoDB.)
  • Сколько UNIQUE ключей на каждом столе? (INSERTs замедляются из-за необходимости проверять наличие дуплекса.)
  • Вы используете INSERT? Один ряд за раз? Или дозированный? (Вставка пакета из 100 строк за раз является оптимальной - в 10 раз быстрее, чем 1 за раз.)
  • Или вы используете LOAD DATA? (Даже быстрее.)
  • Какая связь между «файлом» и «таблицей»? То есть вы загружаете много маленьких файлов в таблицу, или каждый файл представляет собой одну таблицу?
  • Имеет ли RAID-массив чередование и / или кэш записи с батарейным питанием?
  • Является ли диск HDD или SSD?
  • Каково время проверки связи между клиентом и сервером? (Вы упомянули «сеть», но не указали близость.)
  • Сколько таблиц? Вы создаете до 1,87 таблиц в секунду? То есть 3 файла для записи и 1 для чтения? (Windows не самая лучшая в быстром открытии файлов.) Это примерно 7 открытий файлов в секунду. (Примечание. При использовании innodb_file_per_table=1. InnoDB нужен только 1 файл на таблицу).

Пожалуйста, укажите SHOW CREATE TABLE для пары больших столов. Пожалуйста, предоставьте образец используемых операторов SQL.

Запрос Уилсона также может быть полезен.

...