database is locked Unable to fetch row SQLite
Следующая проблема
Программа, аналог UpdateScannera'a в FireFox
Цель - сканировать сайты на предмет наличия новых ссылок
Допустим, добавили 10 сайтов, и в начальный момент времени все они запускаются на анализ и в базу добавляется порядка 300 ссылок по каждому сайту, притом - параллельно и с использованием транзакций для усорения работы
Итого порядка 3000 - 4000 вставок по 300-400 параллельных
Как следует из сабжа, бд - SQLite
Проблема - БД, судя по всему блокируется на время транзакции, и прога выкидывает ошибку: database is locked Unable to fetch row
Собственно, такая ошибка может появляться и при каких-то других случаях, суть в том, что база лочится, и это ведёт к ошибке
Вопрос
Как обойти эту проблему, какие варианты решения Вы знаете?
P.S. Пробовал
Код:
db.setConnectOptions("QSQLITE_BUSY_TIMEOUT=10000");
//===================
QSqlQuery query(db);
if (!query.exec("PRAGMA locking_mode = exclusive")) {
QMessageBox::warning(0, "Error", query.lastError().text());
}
if (!query.exec("PRAGMA synchronous = off")) {
QMessageBox::warning(0, "Error", query.lastError().text());
}
if (!query.exec("PRAGMA temp_store = MEMORY")) {
QMessageBox::warning(0, "Error", query.lastError().text());
}
if (!query.exec("PRAGMA journal_mode = off")) {
QMessageBox::warning(0, "Error", query.lastError().text());
}
//===================
QSqlQuery query(db);
if (!query.exec("PRAGMA locking_mode = exclusive")) {
QMessageBox::warning(0, "Error", query.lastError().text());
}
if (!query.exec("PRAGMA synchronous = off")) {
QMessageBox::warning(0, "Error", query.lastError().text());
}
if (!query.exec("PRAGMA temp_store = MEMORY")) {
QMessageBox::warning(0, "Error", query.lastError().text());
}
if (!query.exec("PRAGMA journal_mode = off")) {
QMessageBox::warning(0, "Error", query.lastError().text());
}
Буду благодарен за любые советы!
Вы удивитесь)
Итааак.....
Код:
if (!query.exec()) {
errorMessage(query.lastError().text() + "\nGetViewsByUrl:1");
while (query.exec() == false) {}
}
errorMessage(query.lastError().text() + "\nGetViewsByUrl:1");
while (query.exec() == false) {}
}
Смысл: если запрос не выполняется сразу, пишем сообщение об ошибке в лог файл функцией errorMessage, и запускаем выполнение команды до тех пор, пока она не выполнится (в нашем случае она будет пытаться выполняться до тех пор, пока база не разлочится)
Такой вот аналог мутексов:)
Если вдруг будет допущена ошибка в SQL запросе - мы узнаем об этом через лог
:facepalm:
Враппер?
QMutex <= делаем глобальным и перед транзакцией mutex->lock, после соответственно unlock
ну или
QSemaphore <= оба с примерами
ну или
QSemaphore <= оба с примерами
Опишу особенности работы программы, чтобы было понятно, что не всё может быть так просто
Сейчас у нас в программе 2 модуля
1. Анализатор
2. GUI модуль, содержащий настройки
Притом, эти 2 модуля = 2 exe'шника
Запуск выполняется следующим образом:
Код:
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QApplication::setQuitOnLastWindowClosed(false);
Config config;
//устанавливаем язык
QTranslator translator;
if (config.lang() == "Russian") {
translator.load("main_ru.qm", ".");
app.installTranslator(&translator);
}
SystemTray tray;
Server server;
server.start();
QProcess process;
//вот тут запускается анализатор
process.start("Scanner.exe");
return app.exec();
}
{
QApplication app(argc, argv);
QApplication::setQuitOnLastWindowClosed(false);
Config config;
//устанавливаем язык
QTranslator translator;
if (config.lang() == "Russian") {
translator.load("main_ru.qm", ".");
app.installTranslator(&translator);
}
SystemTray tray;
Server server;
server.start();
QProcess process;
//вот тут запускается анализатор
process.start("Scanner.exe");
return app.exec();
}
Такое разделение связано с тем, что, если совмещать GUI и анализатор, надо:
1. Выносить анализатор в отдельный поток
Да, это круто, мы так и делали
Но у нас нужно
1. Сканировать страницы = использование QWebPage
Мы выяснили это, когда у нас уже было всё написано
А использование QWebPage необходимо делать в GUI потоке!
То есть необходимо было делать такой хитрый трюк, выносить инициализацию QWebPage из потока, и потом делать сигнал-слот связку
Мы так и сделали, но это не решило проблему, потому что такой вариант вызывал тормоза в GUI, как ни крути
Решение с разделением проекта на 2 exe'шника не вызывает никаких сомнений
БД - одна
Доступ к ней осуществляется из 2ух exe'шников, таким образом, мутексы тут врят ли помогут
Как мы свяжем мутексы в классе для работы с БД, который используется в 2ух разных проектах?
Я сомневаюсь, что это будет работать...
2 экзешника это ведь не 2 потока...
Цитата: Lindemann66
...
Сейчас у нас в программе 2 модуля
1. Анализатор
2. GUI модуль, содержащий настройки
Притом, эти 2 модуля = 2 exe'шника
...
Сканировать страницы = использование QWebPage
...
:facepalm:
Критиковать то любой может)
Отказался бы от Qt и использовал по максимуму возможности plugin-движка
не мы принимаем такие решения
он же не на C#
Цитата: Lindemann66
К тому же в plugin движке такое врят ли было бы проще сделать
он же не на C#
он же не на C#
Я имел ввиду api предоставляемое sdk плагинам. Ну а вообще дело ваше, хотябы впишите туда msleep(1); <- снизит загрузку цп со 100%
[COLOR="silver"]
Юбилейное - 512-е сообщение x D[/COLOR]
QThread::msleep
а api и sdk да - с ie както проблематично, если для мозилы есть например https://developer.mozilla.org/En/Plugins официальный сдк, то для ie официальный както не гуглится вообще :) с ходу гуглятся только платная вещица и давно архивная непонятно что ну и офф. инфа
а api и sdk да - с ie както проблематично, если для мозилы есть например https://developer.mozilla.org/En/Plugins официальный сдк, то для ie официальный както не гуглится вообще :) с ходу гуглятся только платная вещица и давно архивная непонятно что ну и офф. инфа
нам правда нужны под все браузеры...
хотя с ие проблемы будут в любом случае)