медленное восстановление базы данных mysql с несколькими потоками (delphi)

0

Мне нужно восстановить множество резервных копий базы данных 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;
  • 0
    Вы знаете, что можете просто использовать mysqldump для восстановления файлов, верно?
  • 0
    @whosrdaddy: Я тоже пытался вызвать mysqldump из моих потоков: производительность была одинаковой. Я также пытался вызвать CreateProcess (cmd.exe / c mysql -u root -pPassword <'+ tmpFn) из моих потоков, но также без изменений
Показать ещё 4 комментария
Теги:
performance
multithreading
restore

1 ответ

0

Похоже, вы используете MyISAM. Это устарело и страдает от "столовых замков", что сильно мешает параллелизму.

Для MyISAM не имеют значения:

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

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

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

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

Запрос Wilson также может быть удобным.

  • 0
    Спасибо Рик Джеймс и Вурсадди за все эти соображения. Узкое место возникает при использовании восстановления через TClientDataset (или потомок). Использование CreateProcess с командой mysql дает мне гораздо более высокую скорость (я, должно быть, упустил из виду, когда я впервые протестировал это). Я отредактировал информацию в моем первоначальном сообщении.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню