Адаптер Qt MySQL отказывается подключаться случайно: невозможно присвоить MYSQL
Я использую QMYSQL для подключения к локальной базе данных. Приложение работает по нескольким потокам. Каждый поток подключается к базе данных с использованием независимого подключения. Иногда Qt вызывает следующую ошибку при попытке подключения к базе данных. В чем проблема?
QMYSQL: Unable to allocate a MYSQL object
Обновление
Добавлен код, используемый для подключения. Этот объект перемещается в поток, имя соединения. critical
- это сигнал, излучаемый в главное окно, чтобы прекратить выполнение приложения после критической ошибки (показывая сообщение). log
- это сигнал, который испускается для регистрации ошибок в базе данных.
void ClientWorker::connect() {
m_database = QSqlDatabase::addDatabase("QMYSQL","wsc");
m_database.setHostName(m_host);
m_database.setDatabaseName(m_databaseName);
m_database.setPort(m_port);
m_database.setUserName(m_db_username);
m_database.setPassword(m_db_password);
if(!m_database.open()) {
QString error = "Unable to connect to database. Reason:\n";
error+= m_database.lastError().text();
log("Unable to connect to database! ", error, "ERROR" );
emit critical(tr("Database Error!"),error);
} else {
log("Connected to datbase successfully.", "", "NOTICE" );
}
Обновление 2
Я понял, что каждый раз, когда соединение выполняется из основного потока (без активных подключений в основном проходе), драйвер не загружается. Я просто добавил небольшой код фиктивного соединения в main()
, который немедленно соединяется и отключается (до того, как какой-либо поток подключится). Добавляя этот код, все работает нормально. Я не уверен, почему потоки не могут подключиться до подключения в основном потоке, но я думаю, что это похоже на ошибку. Надеюсь, что это помогает кому-то, Я занял 3 дня:/
Ответы
Ответ 1
Вам может не понравиться последнее обновление, но у меня есть теория, основанная на нем: this > указывает, что mysql_library_init()
нужно вызывать из main()
для многопоточных Приложения.
Если вы посмотрите в источник плагина Qt, этот метод завернут в qLibraryInit()
, который вызывается из конструкторов QMYSQLDriver : QSqlDriver
, который, в свою очередь, я считаю, что создается косвенно с помощью addDatabase()
в контексте использования.
MySQL docs отмечают, что mysql_library_init()
может быть защищен мьютексом, что повлечет за собой код QtSql, защищающий всю конструкцию QSqlDriver, что я не думаю, что это так. Поэтому я не уверен, что это будет считаться ошибкой кода Qt или пробелом в документации.
Все это соответствует поведению, которое вы описали, но я все еще сомневаюсь в себе - если это правильно, меня удивляет, что больше людей не сталкиваются с этим, и это не более очевидно на SO и других форумах. Я предполагаю, что немного необычно делать свою первую работу с БД на порожденном потоке по сравнению с некоторой начальной работой в основном потоке?
Ответ 2
В Qt есть ошибка, связанная с QSqlDatabase:: isOpen().
http://bugreports.qt-project.org/browse/QTBUG-223
QSqlQuery:: lastError() должен дать вам сообщение об ошибке, если ваш запрос через QSqlQuery:: exec() завершился с ошибкой. Также QSqlDatabase:: isOpen() должен сообщить о состоянии вашего соединения, QSqlDatabase:: lastError() также доступен