Я написал простую программу, которая порождает 10 потоков, каждый поток открывает базу данных (общую для всех потоков) или создает ее (с опцией «Write-Ahead Log»), если открытие не удается, создает таблицу в базе данных, а затем в бесконечный цикл, в котором он добавляет одну строку за раз в свою таблицу. Я обнаружил, что программа пропускает около 2 дескрипторов каждые 5 минут, я попробовал инструмент под названием Memory Verify, который сообщает мне, что утечка дескрипторов — это блокировки файлов SQLite3 (строка 34034 в версии 3.7.13), но я не уверен, что ошибка находится в SQLite или в том, как я его использую.
Я не указал какой-либо параметр компилятора для сборки SQLite3, поэтому он построен как многопоточный, и, насколько я понимаю, многопоточный должен нормально работать в моем случае, поскольку каждый поток имеет свое собственное соединение SQLite.
Чтобы открыть или создать базу данных, я использую следующий код:
bool Create()
{
int iFlags = 0;
iFlags = iFlags | SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_CREATE;
return sqlite3_open_v2(dbName_sm.c_str(), &pHandle_m, iFlags, 0) == SQLITE_OK;
}
bool Open()
{
int iFlags = 0;
iFlags = iFlags | SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX;
return sqlite3_open_v2(dbName_sm.c_str(), &pHandle_m, iFlags, 0) == SQLITE_OK;
}
Жесткий цикл в каждом потоке вызывает ExecuteQuery, который подготавливает, шагает и завершает оператор INSERT:
bool ExecuteQuery(const std::string& statement)
{
bool res = Prepare(statement);
if(!res)
{
return false;;
}
SQLiteStatus status = Step();
Finalize();
res = (ESuccess == status || EDatabaseDone == status);
return res;
}
bool Prepare(const std::string& statement)
{
return sqlite3_prepare_v2(pHandle_m, statement.c_str(), -1, &pStmt_m, 0) == SQLITE_OK;
}
enum SQLiteStatus { ESuccess, EDatabaseDone, EDatabaseTimeout, EDatabaseError };
SQLiteStatus Step()
{
int iRet = sqlite3_step(pStmt_m);
if (iRet == SQLITE_DONE)
{
return EDatabaseDone;
}
else if (iRet == SQLITE_BUSY)
{
return EDatabaseTimeout;
}
else if (iRet != SQLITE_ROW)
{
return EDatabaseError;
}
return ESuccess;
}
bool Finalize()
{
int iRet = sqlite3_finalize(pStmt_m);
pStmt_m = 0;
return iRet == SQLITE_OK;
}
Ребята, вы видите какую-либо ошибку в моем коде или это известная проблема в SQLite? Я пару дней пытался гуглить, но ничего не нашел по этому поводу.
Большое спасибо за Вашу помощь.
С уважением,
Андреа
P.S. Я забыл сказать, что провожу тест на 64-битном ПК с WinXP, компилятор VS2010, приложение скомпилировано в 32-битной версии, версия SQLite 3.7.13...