mysql数据库 c api(一)

来源:互联网 发布:长沙淘宝主播招聘 编辑:程序博客网 时间:2024/05/17 23:53

c连接mysql数据库

根据mysql 5.6 manual c api那一章,简述了一些重点,并没有注重细节,主要是为了一个大概整体的印象.任何一个东西学透,都是要花很大的功夫和精力.这里只简述unix和unix-like方面的内容,不关心windows方面.

23.8.1 MySQL C API Implementations

讲述几点.

1)两个库文件

libmysqlclient: mysql client 端包含的库文件.一般是通过网络连接到服务器端.个人认为使用这个库文件保险些.
libmysqld: 安装mysql server端包含的库文件.只与本地服务器通信.

两个库文件接口相同.

安装mysql server,包含了两个库文件.

安装mysql connector/c distribution包含库文件libmysqlclient.

以上两中安装方式,只需要一种即可,最好不要同时安装两种,否则可能出现问题.

刚查下服务器上的mysql cluster,因为mysql cluster分为访问节点,数据节点,管理节点.好像只要安装了mysql cluster不管是什么节点,都会包含两个库文件.安装cluster可以理解安装了server.

2)动态库与静态库.

unix,unix-like动态库以.so结尾.静态库以.a结尾.

3)在mysql 5.5版本后,两个库文件都是线程安全的.5.5版本之前,在有后缀为_r的版本库,表示为线程安全的,现在5.5之后的_r的库只是一个符号链接.查了下服务器上mysql cluster(版本7.2.x)上,_r版本库果然是符号链接.


23.8.2 Simultaneous MySQL Server and MySQL Connector/C Installations

简述了同时安装mysql server 与mysql connector可能出现错误的情况.不关心.具体链接如下.

http://dev.mysql.com/doc/refman/5.5/en/c-api-multiple-installations.html


23.8.3 Example C API Client Programs

获取例子,据说在安装mysql时,本机上有.不过,没找到.


23.8.4 Building and Running C API Client Programs

23.8.4.1 Building C API Client Programs


编译时,也许需要明确指定头文件-I (i的大写,这里看着像小写L似得 - -).
-I/usr/local/mysql/include
mysql 客户端必须 指定-lmysqlclient选项,也许需要明确指定库文件位置-L选项.
-L/usr/local/mysql/lib -lmysqlclient
根据自己系统的不同调整参数.
可以通过使用mysql_config选项更简单些,查看参数.mysql_config打印出编译链接的选项.
shell> mysql_config --cflagsshell> mysql_config --libs
也可以直接使用.
shell> gcc -c `mysql_config --cflags` progname.cshell> gcc -o progname progname.o `mysql_config --libs`

在链接mysql库文件时可能出现的错误.在mysql5.6上,mysql client库支持ssl传输.编译时不需要明确 指定参数-lssl or -lcrypto.

1)当链接器找不到mysql client的库时,会表现为以mysql_开头的undefined-reference错误.
/tmp/ccFKsdPa.o: In function `main':/tmp/ccFKsdPa.o(.text+0xb): undefined reference to `mysql_init'/tmp/ccFKsdPa.o(.text+0x31): undefined reference to `mysql_real_connect'/tmp/ccFKsdPa.o(.text+0x69): undefined reference to `mysql_error'/tmp/ccFKsdPa.o(.text+0x9a): undefined reference to `mysql_close'
解决这个问题,编译时加上-Ldir_path -lmysqlclient.可以通过mysql_config --libs显示lib路径,上文述.

2)链接时出现floor 符号 没有undefined.链接数学函数库时在编译/链接最后加上-lm选项.

3)如果其他一些函数的undefined-reference错误出现,像connect.查看手册,在编译时增加相应库的链接命令.

4)如果出现undefined-reference错误像以下函数在系统中不存在.这意味着当前系统安装的mysql不是完全适合当前系统,需要重新下载安装相应版本的mysql.
mf_format.o(.text+0x201): undefined reference to `__lxstat'


23.8.4.2 Writing C API Threaded Client Programs

库对每个连接都是线程安全的,大部分的函数是线程安全的.最大的问题是net.c的子程序,从socket中读取,并不是中断-安全(interrupt-safe).如果为SIGPIPE中断分配了中断句柄,那么socket是线程安全的.
为了避免由连接中断导致的程序 崩溃,mysql会在调用my_library_init(),mysql_init(),或者mysql_connect时对SIGPIPE加锁.如果使用自己的SIGPIPE句柄,首先调用mysql_library_init(),然后再安装处理程序.
在编译连接时,包含线程库.

多线程之间可以共享数据库连接.
在同一时间多线程不能同时使用相同的链接,任一时间,只能有一个线程使用数据库连接.具体体现在保证一个线程使用mysql_query和mysql_store_result完成前,不能有其他线程使用这个数据库连接.共享一个数据库连接时,最好对mysql_query和mysql_store_result一起加锁(每次对数据库的操作,同时锁住一对函数).当mysql_store__result返回时,锁释放,其他线程可以使用这个连接.使用mysql_use_result(),必须保证在结果集合close前,没有其他线程使用相同的连接.最好还是使用mysql_store_result()函数.
调用mysql_init(),mysql会创建针对这个线程的一个明确的线程变量.如果在 调用mysql_init函数之前,使用其他mysql函数,则可能会产生core dump 错误.为了避免错误,应遵循以下原则
1.在调用mysql其他函数时,先调用mysql_library_init,这个不是线程安全的,所以在创建线程前调用,并在线程使用时,进行互斥访问(加锁).
2.先调用mysql_thread_init()函数.但是调用mysql_init()函数时,函数会去调用mysql_thread_init()函数.
3.在线程中,调用pthread_exit之前调用mysql_thread_end(),释放线程变量.
调用mysql_connect时,函数会调用mysql_init().

个人总结:
线程这一块,想起之前写程序使用slqite一些疑惑.创建进程,进程中创建一个数据库连接,然后进程fork很多子进程.在同时操作数据库时,出现了意外现象,即数据错乱,后来自己在进程间加锁才解决这个问题.共享一个数据库连接的好处是,节约时间,减少了创建和销毁连接的时间,但同时,我们自己需要处理好同步关系.mysql这块也一样,mysql_query和mysql_store_result和sqlite对应的一对函数一样,一个萝卜对一个坑,用完了 ,才允许其他线程使用这一对函数.这里mysql文档建议我们使用线程共享连接时这对函数时加锁,线程不共享,各自负责各自的连接,互斥问题就由mysql数据库本身解决.同时建议我们使用mysql_store_result.

23.8.4.3 Running C API Client Programs

程序运行时可能出现的错误.
升级后,已编译的程序可能出现问题,像出现命令不同步,core dumps错误,程序可能是引入使用了低版本的头文件或者库文件.这种情形下,检查编译环境mysql.h文件和libmysqlclient.a的时间,验证是否是最新的mysql.当共享库文件主版本号改变时,例如 libmysqlclient.so.17到xxx.18版本,最好重新重新编译.更多的关注下主版本号,例如libmysqlclient.so.18.1.0,主版本号为18,在主版本号一致的情况下,可以升级库,程序应该可以继续工作.
备注句:linux ldd命令可以查看依赖的库文件.
运行时出现undefined-reference错误,如果错误的开头是mysql_或者libmysqlclient library cannot be found.这可能是由于系统找不到共享库libmysqlclient.so.解决的方法是,告诉系统库文件位置.有以下几种方式.
1)增加libmysqlclient.so文件的位置作为环境变量 LD_LIBRARY_PATH or LD_LIBRARY
2)拷贝共享库文件到系统会查询搜索的目录下,像/lib,然后运行ldconfig命令更新共享库的信息.
如果应用使用的是mysql server的库,则可能报libmysqld的错误而不是libmysqlclient的错误,解决 方式与libmysqlclient一样.

暂时写到这了.

0 0