2016-07-13 51 views
11

Używam QMYSQL do łączenia się z lokalną bazą danych. Aplikacja działa na kilku wątkach. Każdy wątek łączy się z bazą danych przy użyciu niezależnego połączenia. Czasami Qt zgłasza następujący błąd, gdy próbuję połączyć się z bazą danych. Jaki jest problem?Qt Adapter MySQL odmawia połączenia losowo: Nie można przydzielić MYSQL

QMYSQL: Unable to allocate a MYSQL object 

Aktualizacja

Dodany kod używany do połączenia. Ten obiekt zostanie przeniesiony do wątku, nazwane zostanie połączenie. critical to sygnał wysyłany do okna głównego w celu zakończenia wykonywania aplikacji po wystąpieniu błędu krytycznego (pokazującego komunikat). log to sygnał, który jest emitowany do rejestrowania zdarzeń w bazie danych.

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"); 
} 

Aktualizacja 2

Właśnie uświadomiłem sobie, że za każdym razem połączenie jest wykonane z głównym wątku, (bez aktywnych połączeń w głównej bieżnika) kierowca nie można załadować. Właśnie dodałem mały fałszywy kod połączenia w main(), który łączy się i rozłącza natychmiast (zanim wątek się połączy). Dodając ten kod, wszystko działa dobrze. Nie jestem pewien, dlaczego wątki nie mogą się połączyć przed połączeniem w głównym wątku, ale myślę, że wygląda jak błąd. Mam nadzieję, że to pomaga komuś, Zajęło 3 dni mojego:/

+1

Czy możesz wyświetlić kod, którego używasz do tworzenia połączeń z bazą danych? – eclarkso

+1

@eclarkso Zaktualizowałem moje pytanie –

+1

Wygląda na to, że używasz tej samej nazwy połączenia ("wsc") we wszystkich twoich wątkach - ale w takim przypadku oczekiwałbym zauważalnego ostrzeżenia, które zwróciłoby twoją uwagę (zakładając, że jest inny połączenia gwintowe są aktywne w tym samym czasie)? Może warto dołączyć identyfikator wątku lub coś do nazwy połączenia, aby upewnić się, że to nie problem? Zakładając, że tak nie jest, czy skompilowałeś wtyczkę Qt MySQL, czy też pochodzi ona od innej firmy? Jaką wersję MySQL? – eclarkso

Odpowiedz

9

Może nie obchodzi po ostatniej aktualizacji, ale mam teorię opartą na nim: this wskazuje mysql_library_init() ma do wywołania z main() dla aplikacji wielowątkowych.

Jeśli spojrzeć w Qt plugin source, że metoda jest owinięty w qLibraryInit(), która jest wywoływana z QMYSQLDriver : QSqlDriver konstruktorów, co z kolei uważam się stworzony pośrednio przez addDatabase() w kontekście użytkowania.

Uwaga: można zabezpieczyć za pomocą muteksu, co pociągnęłoby za sobą kod QtSql chroniący wszystkie konstrukcje QSqlDriver, czego nie sądzę. Nie jestem więc pewien, czy byłby to błąd kodu Qt, czy luka w dokumentacji.

Wszystko to pasuje do zachowania, które opisałeś, ale wciąż mam wątpliwości co do siebie - jeśli to prawda, zaskakuje mnie to, że więcej osób nie wpadło na to i nie jest to bardziej widoczne na SO i innych forach. Sądzę, że jest to trochę niezwykłe, aby wykonać pierwszą aktywność DB w zarodku, a przynajmniej część początkowej pracy w głównym wątku?

+1

To jest dokładnie przyczyna niepowodzenia, a nigdzie nie jest udokumentowane w Qt. dzięki –

+1

Znaleziono https://bugreports.qt.io/browse/QTBUG-31468 po fakcie i zgłosił https://bugreports.qt.io/browse/QTBUG-54872 jako powiązany, ale oddzielny problem. – eclarkso

-1

Istnieje błąd związany z QSqlDatabase :: isOpen() w Qt. http://bugreports.qt-project.org/browse/QTBUG-223

QSqlQuery :: lastError() powinien dać błąd, jeśli zapytanie przez QSqlQuery :: exec() nie powiodło się. Również QSqlDatabase :: ISOpen() powinny zgłosić ten stan połączenia, QSqlDatabase :: lastError() jest również dostępny

+1

Ten błąd jest zamknięty jako nieważny. I jest to związane z Qt3, które było dawno przestarzałe. Nawet nie Qt4. –