Мне нужно восстановить множество резервных копий базы данных 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;
Похоже, вы используете MyISAM. Это устарело и страдает от "столовых замков", что сильно мешает параллелизму.
Для MyISAM не имеют значения:
-SET FOREIGN_KEY_CHECKS=0;
-SET autocommit=0;
Некоторые вопросы, связанные с проблемой:
AUTO_INCREMENT
?UNIQUE
ключей на каждой таблице? (INSERTs
замедляются необходимостью проверки дубликатов.)INSERT
? Один ряд за раз? Или собрали? (Вставка партии по 100 строк за раз - оптимальная - в 10 раз быстрее, чем 1 за раз).LOAD DATA
? (Даже быстрее.)innodb_file_per_table=1
) Предоставьте SHOW CREATE TABLE
для нескольких больших таблиц. Пожалуйста, укажите образец используемых SQL-операторов.
Запрос Wilson также может быть удобным.