如何防止打开文件使用MySQL连接器
它显示的错误代码在C++中太多:Can't create socket(24)
,经过我的调查,我知道那是达到open_files_limit
,我检查在MySQL中show global variables like 'open%';
和值是5000000
,所以我的代码必须它有一些问题。如何防止打开文件使用MySQL连接器
这里是我的简单的代码:
class DB {
public:
double query1();
double query2();
double query3();
};
main() {
DB handler;
for(int i=0;i<100000;i++) {
handler.query1();
handler.query2();
handler.query3();
}
}
我写了一个类处理3的查询,并在循环中运行它,我怎么能阻止打开文件限制问题,在这个类
这里的查询代码:
double query1(string pair) {
double get_prob;
try {
/* Create a connection */
driver = get_driver_instance();
con = driver->connect("localhost", "root", "nlpgroup");
/* Connect to the MySQL test database */
con->setSchema("em_im");
stmt = con->createStatement();
stringstream stmvar;
stmvar << "select prob from em where pair='" << pair << "'";
string stmvarstr = stmvar.str();
cout << stmvarstr << endl;
res = stmt->executeQuery(stmvarstr); // replace with your statement
while (res->next()) {
get_prob = atof(res->getString(1).c_str());
}
res->close();
stmt->close();
con->close();
delete res;
delete stmt;
delete con;
} catch (sql::SQLException &e) {
cout << "# ERR: SQLException in " << __FILE__;
cout << "(" << __FUNCTION__ << ") on line " << __LINE__ << endl;
cout << "# ERR: " << e.what();
cout << " (MySQL error code: " << e.getErrorCode();
cout << ", SQLState: " << e.getSQLState() << ")" << endl;
}
return get_prob;
}
show global variables like 'open%';
在MySQL
除了MySQL,你的操作系统也可能会施加限制。对于linux,看看/etc/security/limits.conf
,在Windows上,this答案可能会帮助你。
但是,如果您需要一个又一个的连接,那么打开一次并保持打开状态直到程序终止是一个更好的选择。这还会为您带来更好的性能 - 而且您可以使用预先准备好的语句来提高性能。我说这个已经在下面的例子...的std::unique_ptr
class DB
{
std::unique_ptr <sql::Connection> con;
std::unique_ptr <sql::PreparedStatement> stmt;
public:
DB();
double query1(std::string const& pair);
};
DB::DB()
: con(get_driver_instance()->connect("localhost", "root", "nlpgroup"))
{
con->setSchema("em_im");
// you might prefer a prepared statement
stmt.reset(con->prepareStatement("SELECT prob FROM em WHERE pair = ?"));
}
double DB::query1(std::string const& pair)
{
double get_prob = 0.0;
try
{
stmt->setString(1, pair);
std::unique_ptr <sql::ResultSet> res(stmt->execute());
while (res->next())
{
get_prob = atof(res->getString(1).c_str());
}
}
catch(sql::SQLException& e)
{
/* ... */
}
return get_prob;
}
用法保证所有对象均即使在例外的情况下,正确删除 - 这,顺便说一下,你的代码没有。我没有明确地打电话给close
- 无论如何它都会在对象的析构函数中调用,所以这很好。
请注意,构造函数现在也可以抛出一个异常,所以您还需要在主函数中尝试catch。根据您的需要,您可以在查询功能中省略try-catch。然而,这改变了行为:即使在两者之间出现故障的情况下,保留所有查询的执行结果,而删除它会导致中止循环。
如果query1()尚未完成,那么运行query2()会发生一些错误?或者它会运行query2()直到query1()结束? –
如果像上面那样运行query1,并且任何异常都会失败,那么将捕获异常,并且对于query2,所有事情都会从头再次开始(除非连接和创建语句,当然如果类似实现)。查询2中再次发生同样的异常并不是不可能 - 但不一定。这取决于你的具体要求,如果继续使用query2更适合,即使query1失败,或者如果没有任何意义(在后一种情况下,你不会在查询中捕获异常,但只在主函数中,那么循环将退出)。 – Aconcagua
多一个问题,我该如何使用c_stmt = con> createStatement();与unique_ptr
看看如何编写[mcve](http://*.com/help/mcve)(提示:将它写入IDE,直到它编译并复制粘贴代码)。请关注正确的格式 - 我这次为你做了这个,你可能想比较一下版本,看看如何做得更好。不希望在这里使用缩进标签,我继续看到这样做的缩进问题... – Aconcagua
请注意,如果遇到异常 - *或*,如果结果集为空,则不会初始化get_prob。你会返回一个单位化的值,如果使用它,你会遇到未定义的行为! – Aconcagua