[Решен] Постоянна mysql връзка



  • Здравейте.

    Вече в няколко проекта срещам проблем със свързаността към mysql.
    Не намирам никакъв начин за проверка дали връзката към базата не се е разпаднала преди да се изпълни заявка. Направил съм следното:
    @
    QSqlDatabase Common::getDatabase()
    {
    QSqlDatabase db;
    if( QSqlDatabase::contains("connname") && QSqlDatabase::database("connname").isValid() ) {
    db = QSqlDatabase::database("connname");
    } else {
    db = QSqlDatabase::addDatabase("QMYSQL", "connname");
    db.setHostName("dhhost");
    db.setDatabaseName("connname");
    db.setUserName("dbuser");
    db.setPassword("dbpass");
    db.open();
    }

    return db;
    

    }
    @

    Класа "Common" има само статични методи, с идеята да мога да ги викам от всяка част на програмата, без да правя обекти само заради една функция. Ползвам го по следния начин:
    @
    QSqlQuery query( Common::getDatabase() );
    query.exec("SELECT * FROM `table");
    @

    Когато връзката към базата не е нарушена от пускането на програмата до спирането и, всичко е наред и с тези функции работят нещата. Но ако връзката прекъсне (свързване към друг доставчик, VPN, спиране на мрежов кабел и други), програмата чака query.exec да приключи, който пък не може да приключи заради нарушената връзка. Търсих какви ли не варианти, isValid() и isOpen() на QSqlDatabase винаги връщат true и с тях не може да се проверява състоянието на връзката.
    Някой от вас намерил ли е решение на този проблем? Единственото което ми идва на ум е да направя wrapper клас който да викам при нови заявки към базата и в него да стартирам конекцията и да я спирам веднага след като заявката приключи. Това разбира се ще дойде и с големия overhead за отваряне на нова конекция всеки път и според мен не е решение. Едва ли във всеки един момент ще имам повече от 1 заявка работеща на дадената връзка, така че метода е възможен, но ме притеснява "разхода" на ресурси и скоростта на работа.



  • Здравей,

    и аз си играя с подобни неща за дипломната ми работа. Не съм ги тествал, защото така и няма да ме накарат да я пусна :D

    Но като цяло за мрежата може да следиш с @QNetworkAccessManager::networkAccessibleChanged@ Според документацията е добре всяка програма да има само една инстанция на QNetworkAccessManager за това аз си го правя глобална променлива и си я достъпвам от където ми трябва. При този сигнал, когато се появи мрежа може да отваряш базата на ново.

    Друго, което мога да те посъветвам е за QSqlDatabase e, да не правиш допълнителен клас.

    Можеш спокойно в main преди да стартираш всичко да извикаш @QSqlDatabase db = QSqlDatabase::addDatabase( "QMYSQL", "connname" );@ Това ще съдаде DB с такова име в някакъв глобален лист. После може да си я достъпваш от там с @QSqlDatabase db = QSqlDatabase::database("connname");@
    Още след създаването на базата и подаваш:
    @
    db.setHostName("dhhost");
    db.setDatabaseName("connname");
    db.setUserName("dbuser");
    db.setPassword("dbpass");
    @
    От там нататък той си ги знае и само ще викаш open(), когато се появи пак връзка. По-чисто ще стане така, според мен ;)



  • Здрасти.

    Мерси за мнението и предложенията.
    В интерес на истината, QNAM използвам на едно единствено място, заедно с WebKit. Това обаче е отделно от това за което ми трябва проверка на връзката с базата. Забравил съм да спомена че базата се намира на отдалечен сървър и идеята е да може да се свързва и тегли информация от нея без значение на какъв интернет се намира клиента и при срив на връзката тя да се възстановява.

    Създаването и отварянето на базата ми се намираха в main, но унифицирах всичко в Common класа, тъй като навсякъде трябваше да повтарям упражнението
    @
    QSqlDatabase db = QSqlDatabase::database("connname");
    QSqlQuery query(db);
    @

    Вярно, не ми съкращава много кода, но според мен с ползването на функцията Common::getDatabase() е по- "чисто".

    За предложението за networkAccessibleChanged намерих "това":http://stackoverflow.com/questions/18365382/how-do-i-get-a-signal-from-qnetworkaccessmanagernetworkaccessiblechanged

    Не ми изглежда да работи коректно, когато има повече от един мрежов интерфейс.... Ще трябва да тествам. Иначе предполагам мога просто с QNAM да проверявам дали въобще имам връзка преди да правя заявки към базата, защото когато програмата стигне до query.exec() просто си забива - таймаута е твърде голям и не намерих начин да го променя :(
    Иначе според теб дали овърхеда за постоянно отваряне и затваряне на връзката към базата ще е проблем? Имам предвид, както писах и в първия пост, да направя отделен клас (или да субкласна QSqlDatabase), от където вече да си изпълнявам заявките на принципа на работа примерно на PHP - без постоянна връзка, когато има заявка - свързва се, изпълнява я, връща резултата и затваря всичко. Дали няма да забавя излишно програмата по тоя начин и да увелича използването на ресурсите? Притеснява ме че QSqlDatabase::close() може и да не затвори връзката ако има все още работещи заявки. Шанс едно на милион, но може да създаде проблеми....



  • Оказа се че проблема има много просто решение, но човек трябва да седне и да прочете малко документацията /facepalm/

    Ето извадка от документацията:
    @
    void QSqlDatabase::setConnectOptions ( const QString & options = QString() )

    Sets database-specific options. This must be done before the connection is opened or it has no effect (or you can close() the connection, call this function and open() the connection again).
    @

    Към тази функция са описани всички опции които потдържа съответния клиент. За MySQL има MYSQL_OPT_RECONNECT.

    На същото място има дадени примери
    @
    ...
    // MySQL connection
    db.setConnectOptions("CLIENT_SSL=1;CLIENT_IGNORE_SPACE=1"); // use an SSL connection to the server
    if (!db.open()) {
    db.setConnectOptions(); // clears the connect option string
    ...
    }
    ...
    @
    В примера използват option=value синтаксис, но проверих (специално за MySQL) дали става ако само се подадат опциите (без "=1") - всичко е ОК, дори и да се смени доставчика или интернета да е прекъснал за момент, клиента се реконектва и няма проблеми. Ако се загуби връзката, програмата "заспива" и чака MySQL клиента да се реконектне, след което всичко се оправя.

    В моя случай това ще ми свърши работа, надявам се и за други да е полезно ;-)



  • Всъщност явно "=1" е необходимо, защото след следващата компилация почна да ми хвърля грешки. Така че правилния синтаксис си остава option=value или примерно

    @
    db.setConnectOptions("MYSQL_OPT_RECONNECT=1;CLIENT_SSL=1");
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.