1. 单线程程序的数据库访问
(1)初始化MySQL库
(2)初始化数据库连接句柄
(3)连接数据库
(4)通过SQL语句操作数据库并处理相应数据
(5)关闭数据库连接
(6)结束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() 来释放未被释放的内存,否则会出现内存泄漏
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