天天看點

mysql Connector C/C++ 多線程封裝

mysql Connector C/C++ 多線程封裝

在網上找了好久,有很多封裝,但是感覺對多線程處理的不多,都不是很理想。封裝完的第一個版本,想法比較簡單,使用一個單例模式,對應一個連接配接,多線程查詢的時候都是在這個連結上完成,如下簡略代碼

class DbClass
{
public:
     open(....)
    {
           mysql_real_connect(mDB);
     }       

     QuerySQL(....)
    { 
           mysql_real_query(mDB);
     } 
protected:
      MYSQL* mDB;

}      

但實際使用中發現隻要多線程一開就報錯,一般就是lost connect之類的錯誤,開始以為就是單純的連接配接斷開,是以在連接配接上面做了一些文章,每次查詢的時候使用ping确定連接配接是否正常,具體ping怎麼寫我這裡就不贅述了,網上有很多文章,加完了Ping,對連接配接設立了逾時時間依然不能解決問題。

查了一下文檔發現在使用多線程時mysql_real_query函數和mysql_store_result函數必須加鎖,由于ping有可能造成連接配接重連,是以在ping裡面也加上了鎖,如下代碼

class DbClass
{
public:
     open(....)
    {
           mysql_real_connect(mDB);
     }       
    
     ping()
     {
mutex.lock();
         mysql_ping();
mutex.unlock();
     }

     QuerySQL(....)
    { 
          mutex.lock();
           mysql_real_query(mDB);
          mutex.unlock();
     } 
protected:
      MYSQL* mDB;

}
      

這次再試終于不報錯了,高興了好長時間,這段代碼也就沒有再看,代碼測試到最後的時候,加上了計時等性能測量就發現問題了,多線程和單線程的用時一樣。。。。問題很明顯,這個其實就是串行通路資料庫的,實質上還是單線程。而且即使單線程由于加的鎖比較多,速度也并不快。

重新思考了下,單連接配接上的多線程貌似肯定是不行了,一個連接配接同一時刻隻能處理一個線程,想明白就好辦了,改成每個線程對應一個連接配接就OK了,而且這樣改由于連接配接并非共享資源,也不需要加互斥,會大大提高效率。

class DbClass
{
public:
     MYSQL*open(....)
    {
MYSQL* pDB;
           mysql_real_connect(pDB);
          return pDB;
     }       
    
     ping(MYSQL* pDB)
     {
         mysql_ping(pDB);
     }

     QuerySQL(MYSQL* pDB, .....)
    { 
           mysql_real_query(pDB);
     } 

  close(MYSQL* pDB)
   {
    mysql_close(pDB);
    }
}

work_thread()
{
  MYSQL* pDB = DbClass::open();  //應該是單例,這裡就用static示意一下

    .....
DbClass::ping(pDB);
DbClass::QuerySQL(pDB);
    .....
DbClass::close(pDB);
}
      

改完之後效果很明顯啊,單線程處理8000條資料(還有各種計算)大概要30秒,10線程處理隻要3秒多一點,甚是欣慰。而且,原先由于鎖比較多單線程處理1000條資料大概也要20秒,現在8000要30秒,提高了很多了,還有優化的地方,不過已經滿足需要了,就這樣吧。

總結一下,mysql多線程的封裝需要注意如下幾點

1. 查詢前要先Ping確定連接配接正常

2. 每個線程對應一個連接配接

3. 若線程的删除和建立比較頻繁,需要在擷取連接配接時使用連接配接池。

轉載于:https://www.cnblogs.com/dangerman/archive/2013/01/17/2864694.html