12.MySQL使用C连接和连接池
连接注意事项:
1)库的位置:在/lib64有一个mysql目录,里面放着mysql客户端的动静态库,链接时要指定库路径和库名称
2)头文件位置:在/usr/include有一个mysql目录,里面存放头文件,其中就有mysql.h
获取mysql客户端版本:mysql_get_client_info()
mysql接口
初始化:MYSQL *mysql_init(MYSQL *mysql); //参数传nullptr即可
MYSQL *mysql_real_connect(MYSQL *mysql, const char *host,
const char *user, const char *passwd,
const char *db, unsigned int port,const char *unix_socket, unsigned long clientflag);
- mysql:mysql_init出来的指针
- host:mysql数据库主机ip
- user:用户名
- passwd:密码
- db:数据库名
- port:端口号
- unix_socket:域间通信,即本地通信,填nullptr即可
- clientflag:填0即可
- 返回值:成功返回mysql指针,失败返回nullptr
关闭连接:void mysql_close(MYSQL *sock);
执行sql语句:int mysql_query(MYSQL *mysql, const char *q); //返回值:成功0返回,返回其他失败
如果获取中文是乱码,mysql_set_character_set(myfd, "utf8");
增删改直接用mysql_query就够用了,对于查,要涉及到查询结果。
MYSQL_RES *mysql_store_result(MYSQL *mysql); //获取MYSQL对象中查询结果
该函数会调用MYSQL变量中的st_mysql_methods中的 read_rows 函数指针来获取查询的结果。同时该函数会返回MYSQL_RES 这样一个变量,该变量主要用于保存查询的结果。同时该函数malloc了一片内存空间来存储查询过来的数据,所以我们一定要记的free(result),不然是肯定会造成内存泄漏的。
理解MYSQL_RES结构:
维护了一个二级指针数组,里面每个元素就是查询出来的一行。每个元素,是一个二级指针,本质就是字符串数组,记录一行中各个字段查询出来的值(字符串)。
这个MYSQL_RES是malloc出来的,用完需要进行释放。不要手动free,调用对应接口:void mysql_free_result(MYSQL_RES *result)。
获取结果行数:my_ulonglong mysql_num_rows(MYSQL_RES *res);
获取结果列数:unsigned int mysql_num_fields(MYSQL_RES *res);
获取列属性:MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *res);
例如:获取到的指针q,q[0].name,获取第一列名称
截取一行内容:MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
特别注意:内部会维护下标,一行一行截取
截取到的行就是字符串数组(MYSQL_RES二级指针数组一个元素),用下标访问即可。
MySQL C API还支持事务:
my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
my_bool STDCALL mysql_commit(MYSQL * mysql);
my_bool STDCALL mysql_rollback(MYSQL * mysql);
mysql连接池实现思路
实现思路:创建一个线程池,线程池启动时会给每个线程建立connect,然后再去执行相应业务。任务队列定义任务结构task时,定义string sql存放sql,定义回调函数cb,将来这个任务由客户端去构建。往后,客户端相应进行数据库操作,都去构建相应的任务task对象,将其入到任务队列中,由线程池内线程执行相应sql语句,执行结果通过回调函数cb获取。
网页用户登录&&注册逻辑
用户使用浏览器客户端,发送HTTP请求,请求方式GET/POST,服务端主机(php,python,java)收到(decode确保完整,反序列化,回调业务),回调业务中构建任务对象task,给对应的C++/C语言写的中间件(数据库连接池等),其内部线程池或进程池负载均衡式地给大批mysql服务端主机(这些主机数据都是同步的,随便查哪一个都行,修改只需修改一个即可)发sql语句。为了效率,还可以加redis缓存,先从缓存中读。