2016-07-13 87 views
11

Sto utilizzando QMYSQL per connettersi a un database locale. L'applicazione viene eseguita su più thread. Ogni thread si collega al database utilizzando una connessione indipendente. A volte Qt genera un errore dopo aver provato a connettermi al database. Qual è il problema?Qt L'adattatore MySQL si rifiuta di connettersi in modo casuale: Impossibile allocare un MYSQL

QMYSQL: Unable to allocate a MYSQL object 

Aggiornamento

aggiunto il codice utilizzato per la connessione. Questo oggetto viene spostato in un thread, la connessione è denominata. critical è un segnale emesso alla finestra principale per terminare l'esecuzione dell'applicazione dopo un errore critico (che mostra un messaggio). log è un segnale che viene emesso per registrare le incidenze nel database.

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

Aggiorna 2

ho capito che ogni volta che si effettua una connessione di filo principale (con connessioni attive in battistrada principale) il driver non carica. Ho appena aggiunto un piccolo codice di connessione fittizio in main() che si connette e disconnette immediatamente (prima che qualsiasi thread si colleghi). Aggiungendo quel codice, tutto funziona bene. Non sono sicuro del motivo per cui i thread non possono connettersi prima di una connessione nel thread principale, ma penso che sembri un bug. Spero che questo aiuti qualcuno, Ho preso 3 giorni miei:/

+1

Puoi mostrare il codice che stai utilizzando per creare le connessioni al database? – eclarkso

+1

@eclarkso Aggiornata la mia domanda –

+1

Sembra che tu stia usando lo stesso nome di connessione ("wsc") su tutti i tuoi thread - ma in tal caso, mi aspetterei un messaggio di avvertimento evidente che avrebbe attirato la tua attenzione (assumendo diversi i collegamenti filettati sono attivi contemporaneamente)? Potrebbe essere opportuno aggiungere l'id del thread o qualcosa al nome della connessione per assicurarsi che non sia questo il problema? Supponendo che non lo sia, hai compilato il plugin Qt MySQL o è arrivato da qualche terza parte? Quale versione di MySQL? – eclarkso

risposta

9

Potrebbe non cura dopo l'ultimo aggiornamento, ma ho una teoria basata su di esso: this indica mysql_library_init() ha essere chiamato da main() per applicazioni multithread.

Se si guarda nel Qt plugin source, tale metodo è avvolto in qLibraryInit(), che si chiama dalle QMYSQLDriver : QSqlDriver costruttori, che a sua volta credo ottenere creato indirettamente da addDatabase() nel vostro contesto di utilizzo.

Il MySQL docs atto che il mysql_library_init() può essere fatto protetto da un mutex, che comporterebbe il codice QtSql proteggere tutta la costruzione QSqlDriver, che non credo che lo fa. Quindi non sono sicuro se questo sarebbe considerato un bug del codice Qt o una lacuna nella documentazione.

Tutto questo si adatta al comportamento che hai descritto, ma sono ancora dubbioso su me stesso: se è corretto, mi sorprende che più persone non si siano imbattute in questo e non sia più evidente in SO e in altri forum. Immagino sia un po 'insolito fare la tua prima attività di DB su un thread generato rispetto ad almeno un lavoro iniziale nel thread principale?

+1

Questo è esattamente il motivo del fallimento, e non è documentato da nessuna parte in Qt. grazie –

+1

Trovato https://bugreports.qt.io/browse/QTBUG-31468 dopo il fatto e segnalato https://bugreports.qt.io/browse/QTBUG-54872 come un problema correlato ma separato. – eclarkso

-1

C'è un bug relativo a QSqlDatabase :: isOpen() in Qt. http://bugreports.qt-project.org/browse/QTBUG-223

QSqlQuery :: lastError() dovrebbe fornire un errore se la query tramite QSqlQuery :: exec() non è riuscita. Anche QSqlDatabase :: isOpen() dovrebbe riferire lo stato della connessione, QSqlDatabase :: LastError() è disponibile anche

+1

Questo bug è chiuso come non valido. Ed è legato a Qt3, che è stato deprecato molto tempo fa. Anche non Qt4. –