如果数据库可到达,如何快速检查?(QT,QML,C ) - Linux

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

本文关键字:QML QT Linux 可到达 数据库 何快速 检查 如果      更新时间:2023-10-16

我将QT与QML和C 一起使用。在我的应用程序上,我使用数据库。如果数据库可以到达,则一切都可以。

我的问题是,我想检查数据库(例如ping)。

我尝试了

    db.setDatabaseName(dsn);
    if(db.isValid())
    {
        if(db.open())
        {
            //std::cout <<"Offene Datenbank";
            connected=true;
        }
        else
        {
            connected=false;
        }

    }
    else
    {
        connected=false;
    }

并将连接值作为结果。但是,如果没有连接,那需要很长的时间(也许30秒)。如果我有数据库连接,我如何快速检查?

可能有一种打破命令的方法。未连接5秒后打开?

我认为一个简单的解决方案就是仅检查数据库dever的ping。您可以使用平台的特定方式进行刺激。

这将在Linux上使用:

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

我已经研究了一个问题。这是我发现的。

问题是在默认DB连接超时 - 太长了。每个DB允许您使用自己的API将其更改为可接受的值。在QT中,有一个常见的DB接口-QSqlDatabase。而且它没有这种方法。您可以通过调用其QSqlDatabase::setConnectOptions方法来设置连接设置,但是它仅接受预定义的选项列表(您可以在QT的帮助中阅读)。

对于PostgreSQL,有一个选项connect_timeout,因此您可以写:

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

对于其他数据库,没有这样的参数。每个DB的连接选项都在其"驱动程序"类中解析,该类别派生QSqlDriver并存储在"驱动程序"库中。

所以,您可以做什么:

  1. 您可以重写数据库的驱动程序,以便接受超时选项。
  2. 您可以使用本机API为每个DB编写单独的代码。

update

事实证明,ODBC具有SQL_ATTR_CONNECTION_TIMEOUT选项。

更新2

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

sql_attr_connection_timeout(ODBC 3.0)

sqluinteger值 对应于等待任何请求的秒数 连接到返回应用程序之前完成。司机 应返回sqlstate hyt00(超时到期) 在与查询无关的情况下可能会超时 执行或登录。

如果ValuePtr等于0(默认值),则没有超时。

应该正常工作...

我建议我有一些单独的线程/类,如果没有发生任何时间,请在某些时间后检查连接和发射信号(使用检查 - 知道连接 - 如果已连接到它,我们已经发现了)。此代码未在我的头顶上从头开始测试和写入。

可能包含一些错误。
/// 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"));
}