简体   繁体   English

如果数据库可以访问,如何快速检查? (Qt,QML,C ++) - Linux

[英]How check fast, if database reachable? (Qt, QML, C++)- Linux

I use qt with qml and c++. 我使用qt和qml和c ++。 On my application i use a database. 在我的应用程序上,我使用数据库。 It all works, if the database is reachable. 如果数据库可以访问,这一切都有效。

My problem is, that i would like to check, if database is reachable (like ping). 我的问题是,我想检查,如果数据库可以访问(如ping)。

I tried 我试过了

    db.setDatabaseName(dsn);
    if(db.isValid())
    {

        if(db.open())
        {
            //std::cout <<"Offene Datenbank";
            connected=true;

        }
        else
        {
            connected=false;
        }


    }
    else
    {
        connected=false;
    }

and give the connected value as result. 并给出连接值作为结果。 But that takes very long (maybe 30 seconds), if there is no connection. 但如果没有连接,这需要很长时间(可能是30秒)。 How i can check fast, if i have a database connection? 如果我有数据库连接,我怎么能快速检查?

Is there maybe a way to break the command .open after 5 seconds not connected? 有没有办法打破命令。打开5秒后没有连接?

I have studied this question a bit. 我有点研究过这个问题。 Here is what I found out. 这是我发现的。

The problem is in default db connection timeout - it is too long. 问题出在默认的数据库连接超时 - 它太长了。 Each db allows you to change it to an acceptable value, using their own API. 每个数据库允许您使用自己的API将其更改为可接受的值。 In Qt there is one common db interface - QSqlDatabase . 在Qt中有一个通用的db接口QSqlDatabase And it does not have such method. 它没有这样的方法。 You can set connection settings by calling it's QSqlDatabase::setConnectOptions method, but it accepts only predefined list of options (which you can read in Qt's help). 您可以通过调用它的QSqlDatabase::setConnectOptions方法来设置连接设置,但它只接受预定义的选项列表(您可以在Qt的帮助中阅读)。

For PostgreSQL there is an option connect_timeout , so you can write: 对于PostgreSQL有一个选项connect_timeout ,所以你可以写:

db.setConnectOptions("connect_timeout=5"); // Set to 5 seconds

For other databases there is no such parameter. 对于其他数据库,没有这样的参数。 Connection options of each db are parsed in it's 'driver' class, which derives QSqlDriver and is stored in a 'driver' library. 每个数据库的连接选项都在它的'driver'类中解析,该类派生QSqlDriver并存储在'driver'库中。

So, what you can do: 那么,你能做什么:

  1. You can rewrite database's driver in order it to accept timeout option. 您可以重写数据库的驱动程序,以便接受超时选项。
  2. You can write separate code for each db, using it's native API. 您可以使用它的本机API为每个数据库编写单独的代码。

UPDATE UPDATE

Turns out, that ODBC has SQL_ATTR_CONNECTION_TIMEOUT option. 事实证明, ODBC具有SQL_ATTR_CONNECTION_TIMEOUT选项。

UPDATE 2 更新2

qsql_odbc.cpp:713 qsql_odbc.cpp:713

} else if (opt.toUpper() == QLatin1String("SQL_ATTR_CONNECTION_TIMEOUT")) {
    v = val.toUInt();
    r = SQLSetConnectAttr(hDbc, SQL_ATTR_CONNECTION_TIMEOUT, (SQLPOINTER) v, 0);

https://msdn.microsoft.com/en-us/library/ms713605(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/ms713605(v=vs.85).aspx

SQL_ATTR_CONNECTION_TIMEOUT (ODBC 3.0) SQL_ATTR_CONNECTION_TIMEOUT(ODBC 3.0)

An SQLUINTEGER value corresponding to the number of seconds to wait for any request on the connection to complete before returning to the application. 一个SQLUINTEGER值,对应于在返回到应用程序之前等待连接上的任何请求完成的秒数。 The driver should return SQLSTATE HYT00 (Timeout expired) anytime that it is possible to time out in a situation not associated with query execution or login. 驱动程序应在任何可能在与查询执行或登录无关的情况下超时的情况下返回SQLSTATE HYT00(超时已过期)。

If ValuePtr is equal to 0 (the default), there is no timeout. 如果ValuePtr等于0(默认值),则没有超时。

Should work fine... 应该工作得很好......

I think one easy solution is to just check the ping of the database sever. 我认为一个简单的解决方案是只检查数据库服务器的ping。 You can use platform specific ways for pinging. 您可以使用特定于平台的方法进行ping操作。

This would work on Linux : 这适用于Linux:

int exitCode = QProcess::execute("ping", QStringList() << "-c 2" << serverIp);
if (exitCode==0) 
{
    // is reachable
} else 
{
    // is not reachable
}

I suggest having some separate thread/class where you check connection and emit signal after some timeout if nothing happens (with a check - knowConnection - if we found out already if its connected). 我建议有一些单独的线程/类,你检查连接并在一些超时后发出信号,如果没有任何反应(带有检查 - knowConnection - 如果我们发现已经连接的话)。 This code is not tested and written from scratch on top of my head.. may contain some errors. 这段代码没有在头顶测试和编写。可能包含一些错误。

/// db connection validator in separate thread
void validator::doValidate() {
 this->knowConnection = false;
 db.setDatabaseName(dsn);
 if(db.isValid())
 {
     QTimer::singleShot(1000, [this]() { 
         if (!this->knowConnection) {
             emit connected(false);dm->connected=false;
         }
     });
     if(db.open())
     {
         //std::cout <<"Offene Datenbank";
         this->knowConnection = true;
         dm->connected=true;
         emit connected(true);
     }
     else
     {
         dm->connected=false;
         this->knowConnection = true;
         emit connected(false);
     }
 } 
 else
 {
     dm->connected=false;
     this->knowConnection = true;
     emit connected(false);
 }
}

/// db manager in different thread
void dm::someDbFunction() {
    if (connected) {
        /// db logic
    }
}

/// in gui or whatever
MainWindow::MainWindow() : whatever, val(new validator(..), .. {      
    connect(val, SIGNAL(connected(bool)), this, SLOT(statusSlot(bool));
    ....
}

void MainWindow::statusSlot(bool connected) {
    ui->statusBar->setText((connected?"Connected":"Disconnected"));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM