文档章节

MySql 基于C_API的数据库封装

吃一堑消化不良
 吃一堑消化不良
发布于 2016/09/27 17:24
字数 1302
阅读 126
收藏 3

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

© 著作权归作者所有

吃一堑消化不良
粉丝 28
博文 188
码字总数 113563
作品 0
浦东
程序员
私信 提问
【原创】modb 功能设计之“支持部分MySQL客户端协议”-1

在 《 modb 功能设计之“支持多消费者单生产者”》中说到:需要有一个单独的线程来处理 sql 语句。本文就针对“ 支持部分 MySQL 客户端协议”做第一部分讲述。 最初的想法是,rabbitmq 客户端...

摩云飞
2013/12/18
124
0
用C二次封装常用数据库的API

概述 采用面向接口的编程方式,对常用数据库,基于官方C接口二次封装数据库操作模块,每个模块由一个h文件、一个c文件、一个测试c文件组成;首选接包者会得到至少90%最多100%的赏金,10%可能...

天台道人
2016/02/28
1K
16
node-transform-mysql , js对mysql封装库,链式调用,文档完善

在我自己的平常开发中很少有见到javascript对sql的封装比较好的库(找了一圈也没找到、应该是暂时我没发现),因此前期的项目中根据自己的项目情况实现了一套封装方法。 最近我准备写一个这样的...

只此一生的我
2017/12/27
0
0
SQL Relay 0.46 发布,SQL 中继器

SQL Relay 0.46 发布,该版本修复了少量的 bug,新增一个 C# 的客户端 API 封装和 ADO.NET 数据提供器。 SQL Relay 是一个持久化的数据库连接池,用来为 Unix 或者 Linux 提供数据库连接池、...

oschina
2012/08/17
536
2
nuxt全栈实践 开源后台源码

写在前面 nuxt-bnhcp是我写的一个全栈商城系统,从前端ui切图到后台mysql以及redis缓存,是一个相对完整且系统的项目,nuxt-bnhcp开源至今,收到了大量的反馈和朋友们遇到的问题以及nuxt-bn...

弹指壹挥间
2018/10/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

二叉树交换左右子树

树的实现类 public class TreeNode {public int val;public TreeNode left;public TreeNode right;public TreeNode(int x) {val = x;}public TreeNode(int val, TreeN......

jxlgzwh
24分钟前
11
0
在Workstation 15上测试vShere 6.7+vCenter Server

想学习vSphere,最好能在自己的电脑上搭建相应的学习环境,如下图所示: _________________________________ | ...

大别阿郎
27分钟前
8
0
centos7上部署vnc服务器并实现远程桌面

centos7上部署vnc服务器并实现远程桌面 centos7上进行一下操作 [root@localhost ~]# yum install tigervnc-server -y#安装vnc服务器 Loaded plugins: fastestmirror, langpacks base | 3.6 ......

恩多
30分钟前
13
0
CSS--表格

一、表格的常用属性 1、边距属性padding(td的mrgin无效) 2、边框属性border 3、尺寸属性 width height 4、文本格式 font-* text-* line-height 5、背景属性 颜色,图片,渐变 二、特有属性...

wytao1995
47分钟前
5
0
zookeeper - leader选举

让我们分析如何在ZooKeeper集合中选举leader节点。考虑一个集群中有N个节点。leader选举的过程如下: 所有节点创建具有相同路径 /app/leader_election/guid_ 的顺序、临时节点。 ZooKeeper集...

Canaan_
58分钟前
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部