MySQL транзакция и буферизованный список запросов - PullRequest
0 голосов
/ 06 июня 2018

У меня есть код C ++, который анализирует файлы и обновляет базу данных MySQL в соответствии с содержимым этих файлов.Я запускаю свой код в Windows 10 с MySQL 5.7, и моя база использует движок InnoDB.Вызовы MySQL выполняются через мою собственную оболочку вокруг libmysql.

В попытке оптимизировать этот код, я добавляю запросы на обновление в буфер до достижения максимального размера буфера, затем отправляю весь буфер(содержащий N обновлений) одновременно.Весь этот процесс выполняется внутри одной транзакции.

Вот как выглядит мой код:

MySQLWrapper.StartTransaction();

string QueryBuffer = "";

// Element count is the number of elements parsed from the files
for( int i = 0 ; i < ElementCount ; ++i )
{
bool FlushBuffer = 
( i> 0 && ! (( i + 1 ) % N) )    ||
( i == ElementCount - 1 ); // determines if we have reached the buffer max number of requests

QueryBuffer += "INSERT INTO mytable (myfield) VALUES (" Element[ i ] ");";

if( FlushBuffer )
{
MySQLWrapper.SendRequest( QueryBuffer );
QueryBuffer.assign("");
}
}
MySQLWrapper.Commit();

Реализация SendRequest (строка запроса) будет в основном:

void SendRequest(string Request)
{
mysql_query( SQLSocket, Request.c_str())
}

Однако при фиксации транзакции транзакция была прервана: MySQL указывает, что состояние неверно для совершения.Я пытался сделать то же самое, но отправлять запросы только по одному, и эта ошибка не возникает в момент фиксации.

Итак, мои 2 вопроса:

  1. Знаете ли вы, почему факт отправки нескольких запросов одновременно нарушает мою транзакцию?
  2. Считаете ли вы, что использование буферизованного списка запросов действительно может оптимизировать мой код?

1 Ответ

0 голосов
/ 06 июня 2018

Вместо нескольких INSERT, создайте один INSERT с несколькими значениями.IOW, перед циклом, добавьте INSERT INTO TABLE (columns), затем внутри цикла добавьте (values), для каждого набора значений.

MySQLWrapper.StartTransaction();

string QueryBuffer = "INSERT INTO mytable (myfield) VALUES ";

// Element count is the number of elements parsed from the files
for( int i = 0 ; i < ElementCount ; ++i )
{
    bool FlushBuffer = 
    ( i> 0 && ! (( i + 1 ) % N) )    ||
    ( i == ElementCount - 1 ); // determines if we have reached the buffer max number of requests

    QueryBuffer += "(" Element[ i ] ")";
    if( flushbuffer ) {
        QueryBuffer += ";";
    } else {
        QueryBuffer += ",";
    }

    if( FlushBuffer )
    {
        MySQLWrapper.SendRequest( QueryBuffer );
        QueryBuffer.assign("");
    }
}
MySQLWrapper.Commit();

В результате SQL-оператор будет выглядеть примерно так:

INSERT INTO mytable
(myfield)
VALUES
(1),
(2),
(3),
(3);
...