MySql 基於C_API的數據庫封裝

1. 單線程程序的數據庫訪問  

        (1)初始化MySQL庫 
  (2)初始化數據庫鏈接句柄 
  (3)鏈接數據庫 
  (4)經過SQL語句操做數據庫並處理相應數據 
  (5)關閉數據庫鏈接 
  (6)結束MySQL庫 
  經過這五個步驟便可實現數據庫的訪問,具體代碼和分析以下: mysql

//1.定義訪問數據庫所需變量 
MYSQL    * myData; 
MYSQL_RES    * res; 
MYSQL_ROW    row;

//2. 初始化MySQL庫和數據庫鏈接句柄 
myData = mysql_init((MYSQL*) 0); 

//3. 設置選項
mysql_options(myData, MYSQL_SET_CHARSET_NAME , 「utf8」);
char cOpt = 1;
mysql_options(myData, MYSQL_OPT_RECONNECT, cOpt);

//4. 鏈接數據庫,MYSQL_IP和MYSQL_PORT表示數據庫的IP和端口 
// MYSQL_ACCOUNT, MYSQL_PASSWORD表示數據庫鏈接的賬號和密碼,MYSQL_DBNAME表示所要訪問的數據庫名 
mysql_real_connect( myData, MYSQL_IP, MYSQL_ACCOUNT, MYSQL_PASSWORD, MYSQL_DBNAME, MYSQL_PORT,NULL, 0 ) 
  
//5. 經過SQL語句操做數據庫並處理相應數據 
  //5.1 新建用戶名爲abcdef,密碼爲123456的記錄 
  mysql_query(myData, "insert into TestTable value(‘abcdef’,’ 123456’)"); 
  //5.2 顯示全部記錄  
  mysql_query(myData, "select * from TestTable"); 
  //5.3 將查詢結果保存到res中 
  res = mysql_store_result( myData ) ; 
  //5.4 逐條顯示記錄 
  int j = 0; 
  while ( row = mysql_fetch_row( res ) ) 
   {//獲取一條記錄 
       j = mysql_num_fields( res ) ;//獲取每條記錄的字段數
        for ( k = 0 ; k < j ; k++ ) 
        {
            printf( 「%s」, row[k] ) ; 
            printf( 「\n」) ; 
        }
  } 
  //5.5 釋放res 
  mysql_free_result( res ) ; 

//6. 檢查數據庫鏈接是否有效,當且僅當設置了MYSQL_OPT_RECONNECT選項有效
unsigned long qwPreId = mysql_thread_id( myData );//重連以前的id
mysql_ping( myData );
unsigned long qwNextId = mysql_thread_id( myData );//重連以後的id

//7. 關閉數據庫鏈接 
mysql_close( myData ); 

//8. 結束MySQL庫 
mysql_library_end(); 

關於代碼的幾點說明: 
  (1)定義變量中的三個數據結構爲訪問MySQL所需,MYSQL結構表示一個數據庫鏈接的句柄,其中包含了數據庫鏈接所需的參數,MYSQL_RES結構表示數據庫訪問中一個查詢的返回結果,MYSQL_ROW結構表示返回結構中的一條記錄; 
  (2)獲取查詢結果res並處理完畢,必須釋放res,不然會形成內存泄露 。
  (3)在單線程時,步驟初始化MySQL庫和數據庫鏈接句柄可合併, 由mysql_init()來處理。該函數會自動調用函數mysql_library_init()來初始化MySQL庫,同時初始化鏈接句柄。 
  (4)mysql_connect()是已經廢棄的方法,它參數的含義和mysql_real_connect()是一致的,惟一不一樣的是MYSQL指針可能爲空,在這種狀況下,API會自動管理這部份內存,這將會致使當鏈接失敗時,沒法獲取錯誤信息,由於獲取錯誤信息須要有效的MYSQL指針 。
  (5)mysql_query()與mysql_real_query() 的區別是mysql_query不能包含任何的二進制數據(例如BLOB字段),由於二進制信息中的\0會被誤判爲語句結束。
  (6)若是頻繁地調用 mysql_init 和 mysql_close 的話,記得在 mysql_close 以後調用 mysql_library_end() 來釋放未被釋放的內存,不然會出現內存泄漏sql

2. 多線程環境下的數據庫訪問 

  多線程環境下的數據庫訪問須要保證線程安全。Windows版本的MySQL C API函數都是線程安全的,除了mysql_library_init(),而咱們剛纔的代碼中使用的mysql_init()函數會自動調用函數 mysql_library_init()來初始化MySQL庫,而在多線程環境下,須要不一樣的初始化代碼和清理代碼。具體過程以下: 
  (1)在主函數中調用mysql_library_init( )來初始化MySQL庫; 
  (2)啓動各數據庫訪問線程 
  (3)主函數等待各個線程的結束 
  (4)調用mysql_library_end( )清理MySQL庫。 
  其中數據庫訪問線程的代碼和單線程數據庫訪問代碼相似,可是須要發生一些變化:  數據庫

//1.定義訪問數據庫所需變量 
MYSQL    * myData; 
MYSQL_RES    * res; 
MYSQL_ROW    row;

//2. 初始化MySQL庫和數據庫鏈接句柄 
mysql_init(); 
mysql_thread_init(); 

//3. 初始化myData 
myData = malloc(sizeof(MYSQL)); 
memset(&myData, 0, sizeof(MYSQL)) 

//4. 設置選項
mysql_options(myData, MYSQL_SET_CHARSET_NAME , 「utf8」);
char cOpt = 1;
mysql_options(myData, MYSQL_OPT_RECONNECT, cOpt);

//5. 鏈接數據庫,MYSQL_IP和MYSQL_PORT表示數據庫的IP和端口 
// MYSQL_ACCOUNT, MYSQL_PASSWORD表示數據庫鏈接的賬號和密碼,MYSQL_DBNAME表示所要訪問的數據庫名 
mysql_real_connect( myData, MYSQL_IP, MYSQL_ACCOUNT, MYSQL_PASSWORD, MYSQL_DBNAME, MYSQL_PORT,NULL, 0 ) 
  
//6. 經過SQL語句操做數據庫並處理相應數據 
  //6.1 新建用戶名爲abcdef,密碼爲123456的記錄 
  mysql_query(myData, "insert into TestTable value(‘abcdef’,’ 123456’)"); 
  //6.2 顯示全部記錄  
  mysql_query(myData, "select * from TestTable"); 
  //6.3 將查詢結果保存到res中 
  res = mysql_store_result( myData ) ; 
  //6.4 逐條顯示記錄 
  int j = 0; 
  while ( row = mysql_fetch_row( res ) ) 
   {//獲取一條記錄 
       j = mysql_num_fields( res ) ;//獲取每條記錄的字段數
        for ( k = 0 ; k < j ; k++ ) 
        {
            printf( 「%s」, row[k] ) ; 
            printf( 「\n」) ; 
        }
  } 
  //6.5 釋放res 
  mysql_free_result( res ) ; 

//7. 檢查數據庫鏈接是否有效,當且僅當設置了MYSQL_OPT_RECONNECT選項有效
unsigned long qwPreId = mysql_thread_id( myData );//重連以前的id
mysql_ping( myData );
unsigned long qwNextId = mysql_thread_id( myData );//重連以後的id

//8. 關閉數據庫鏈接 
mysql_close( myData ); 

//9. 結束MySQL庫 
mysql_thread_end();

3. 鏈接池

    (1) 初始化多個connection,每一個connection包含數據庫初始化和關閉,鏈接池採用單例模式安全

    (2) 選取connection,異常返回空數據結構

    (3) 關閉多個connection並回收鏈接池資源多線程

    鏈接池可參考:http://www.oschina.net/code/snippet_583625_19818#32990函數

相關文章
相關標籤/搜索