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函数

相关文章
相关标签/搜索