如何防止打开文件使用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; 
} 
+0

看看如何编写[mcve](http://*.com/help/mcve)(提示:将它写入IDE,直到它编译并复制粘贴代码)。请关注正确的格式 - 我这次为你做了这个,你可能想比较一下版本,看看如何做得更好。不希望在这里使用缩进标签,我继续看到这样做的缩进问题... – Aconcagua

+0

请注意,如果遇到异常 - *或*,如果结果集为空,则不会初始化get_prob。你会返回一个单位化的值,如果使用它,你会遇到未定义的行为! – Aconcagua

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。然而,这改变了行为:即使在两者之间出现故障的情况下,保留所有查询的执行结果,而删除它会导致中止循环。

+0

如果query1()尚未完成,那么运行query2()会发生一些错误?或者它会运行query2()直到query1()结束? –

+0

如果像上面那样运行query1,并且任何异常都会失败,那么将捕获异常,并且对于query2,所有事情都会从头再次开始(除非连接和创建语句,当然如果类似实现)。查询2中再次发生同样的异常并不是不可能 - 但不一定。这取决于你的具体要求,如果继续使用query2更适合,即使query1失败,或者如果没有任何意义(在后一种情况下,你不会在查询中捕获异常,但只在主函数中,那么循环将退出)。 – Aconcagua

+0

多一个问题,我该如何使用c_stmt = con> createStatement();与unique_ptr c_stmt;声明,它会发生不匹配的类型'std :: unique_ptr <_tp _dp>'和'sql :: Statement *' –