如果数据库可访问,如何快速检查? (Qt、QML、C++)- Linux
Posted
技术标签:
【中文标题】如果数据库可访问,如何快速检查? (Qt、QML、C++)- Linux【英文标题】:How check fast, if database reachable? (Qt, QML, C++)- Linux 【发布时间】:2015-05-12 06:32:18 【问题描述】:我将 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 秒未连接后中断命令 .open?
【问题讨论】:
可访问是指您要检查文件是否已创建?或者你有正确的权限?还是两者兼而有之? 我想知道,如果我能像 ping 一样访问服务器。由于我在服务器上的配置文件,如果我可以访问服务器 IP,我应该写/读。 如果我无法访问数据库服务器,应用程序应该返回 false,如果我可以访问它或建立连接,则返回 true 【参考方案1】:我认为一个简单的解决方案是只检查数据库服务器的 ping。您可以使用平台特定的方式进行 ping。
这适用于 Linux:
int exitCode = QProcess::execute("ping", QStringList() << "-c 2" << serverIp);
if (exitCode==0)
// is reachable
else
// is not reachable
【讨论】:
我认为这可以与给出的其他答案结合使用。如果您无法 ping 服务器,您肯定无法建立连接。该信息通过 ping 快速返回。【参考方案2】:我已经研究了这个问题。这是我发现的。
问题在于默认的数据库连接超时 - 它太长了。每个 db 都允许您使用它们自己的 API 将其更改为可接受的值。在 Qt 中有一个通用的数据库接口 - QSqlDatabase
。而且它没有这样的方法。您可以通过调用它的QSqlDatabase::setConnectOptions
方法来设置连接设置,但它只接受预定义的选项列表(您可以在 Qt 的帮助中阅读)。
对于PostgreSQL
,有一个选项connect_timeout
,所以你可以写:
db.setConnectOptions("connect_timeout=5"); // Set to 5 seconds
对于其他数据库,没有这样的参数。每个数据库的连接选项都在它的“驱动程序”类中进行解析,该类派生QSqlDriver
并存储在“驱动程序”库中。
那么,你可以做什么:
-
您可以重写数据库的驱动程序以使其接受超时选项。
您可以使用每个数据库的原生 API 为每个数据库编写单独的代码。
更新
原来,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 (Timeout expired) 在与查询无关的情况下可能超时 执行或登录。
如果 ValuePtr 等于 0(默认值),则没有超时。
应该可以正常工作...
【讨论】:
我有一个 odbc 驱动程序,但我应该选择 SQL_ATTR_CONNECTION_TIMEOUT 选项,确定吗? 好吧,这很尴尬。我从来没有使用过 ODBC,所以我没有检查它的连接选项。是的,我想你是对的 -SQL_ATTR_CONNECTION_TIMEOUT
正是你所需要的。
hmh 我在我的代码中使用了它,但它不像以前那样工作得更快
你设置了什么值?
db.setConnectOptions("SQL_ATTR_CONNECTION_TIMEOUT=5;SQL_ATTR_LOGIN_TIMEOUT=5");如果(db.open())连接=真; 其他 连接=假; 【参考方案3】:
我建议有一些单独的线程/类,您可以在其中检查连接并在超时后发出信号,如果没有任何反应(检查 - knowConnection - 如果我们已经发现它是否已连接)。 这段代码没有经过我的头顶测试和从头开始编写..可能包含一些错误。
/// 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"));
【讨论】:
单次计时器在一个间隔后中止。但我在拍摄一个时没有问题。问题是长时间的延迟 如果我理解你.. 现在延迟将是 1 秒,之后如果 db.open() 中没有任何反应,单次发射会发出我们没有连接的信号。如果您有连接,我认为 db.open() 会立即返回(因此将 knowConnection 设置为 true 等)?嗯..所以计时器只工作一次..我会考虑的。 默认超时时间长的原因是在某些情况下连接到数据库可能需要很长时间。我曾经在一个有许多远程数据库服务器的项目上工作。我们的典型连接时间是 7 秒。有时更长,但很少,如果更短的话。如果您使用此实现,则值得测量您的连接时间并相应地调整一次拍摄的长度。以上是关于如果数据库可访问,如何快速检查? (Qt、QML、C++)- Linux的主要内容,如果未能解决你的问题,请参考以下文章
如何在一个 qt qml 窗口中运行和显示 4 个可执行文件?