mysql连接池的实现

概要:本文介绍mysql连接池的实现,要求读者了解线程池

一、为什么需要mysql连接池?

资源复用 :不使用连接池,每次数据库请求都新建一条连接,将耗费系 统资源。 流程如下:

  1. 通过三次握手建立 TCP 连接
  2. MySQL 认证
  3. SQL 执行
  4. 通过四次挥手断开 TCP 连接

更快的系统响应速度

1.一次连接建立和销毁,可复用同一条连接多次执行 SQL 语句。

2.统一的连接管理,避免数据库连接泄露

二、mysql连接池运行原理

在这里插入图片描述

在这里插入图片描述

三、代码实现

1.结构体定义
typedef struct task_t {struct task_t *next; // 指向下一个任务节点int clientfd; // 客户端fdchar SQL[MAX_SQL_LENGTH]; // SQL语句缓冲区} task_t;typedef struct task_queue_t { // task队列task_t *head; // 指向队列的第一个task节点task_t *tail; // 指向队列的最后一个task节点int block; // 阻塞标志pthread_spinlock_t lock; // 自旋锁变量pthread_mutex_t mutex; // 互斥锁变量pthread_cond_t cond; // 条件变量} task_queue_t;typedef struct argc {MYSQL *mysql;task_queue_t *queue;
} argc;
2.资源创建

a.任务队列

task_queue_t *task_queue_create() { // 创建一个任务队列int ret;task_queue_t *queue = (task_queue_t *)malloc(sizeof(task_queue_t));if (queue) {ret = pthread_mutex_init(&queue->mutex, NULL);if (ret == 0) {ret = pthread_cond_init(&queue->cond, NULL);if (ret == 0) {pthread_spin_init(&queue->lock, 0);queue->head = NULL;queue->tail = NULL;queue->block = 1;return queue;}}free(queue);}return NULL;}

b.mysql连接句柄

void mysql_conn_init(MYSQL* mysql) {mysql_init(mysql); // 初始化mysql句柄// 连接到MySQL数据库mysql_real_connect(mysql, MYSQL_SERVER_IP, MYSQL_SERVER_USERNAME, MYSQL_SERVER_PASSWORD, MYSQL_SERVER_DEFAULT_DB, MYSQL_SERVER_PORT, NULL, 0);}
2.sql任务的添加、执行

a.push、pop

void add_task(task_queue_t *queue, task_t *task) { // 向任务队列中添加一个taskpthread_spin_lock(&queue->lock);if (!queue->tail) {queue->tail->next = task;queue->tail = task;}else {queue->head = task;queue->tail = task;}pthread_spin_unlock(&queue->lock);pthread_cond_signal(&queue->cond);
}void *pop_task(task_queue_t *queue) { // 从任务队列中取出一个任务pthread_spin_lock(&queue->lock);if (queue->head == NULL) {pthread_spin_unlock(&queue->lock);return NULL;}// 取出队列中第一个任务task_t *task;task = queue->head;queue->head = task->next;//判断队列是否为空if (queue->head == NULL) {queue->tail = queue->head;}pthread_spin_unlock(&queue->lock);return task;
}task_t *get_task(task_queue_t *queue) { // 原子地从队列中取出一个任务task_t *task;while ((task = pop_task(queue)) == NULL) {pthread_mutex_lock(&queue->mutex);if (queue->block == 0) {pthread_mutex_unlock(&queue->mutex);return NULL;}pthread_cond_wait(&queue->cond, &queue->mutex);pthread_mutex_unlock(&queue->mutex);}return task;
}

b.执行任务并将mysql服务器的回复信息转发给客户端

void *mysql_conn_thrd_worker(void *argc) {task_t *task;struct argc *arg = (struct argc*)argc;task_queue_t *queue = arg->queue;MYSQL *mysql = arg->mysql;while (!destroy_pool) {task = get_task(queue);if(!task) break;// 执行其中的SQL语句mysql_real_query(mysql, task->SQL, strlen(task->SQL)); // 注入sql语句MYSQL_RES *res = mysql_store_result(mysql); // 存储mysql返回信息char response[64];// 将mysql回复结果cpoy进responseif (res) {MYSQL_ROW row;row = mysql_fetch_row(res);if (row) {snprintf(response, sizeof(response), "%s", row[0]); // 假设结果为字符串类型,仅复制第一列数据} else {snprintf(response, sizeof(response), "No result found");}mysql_free_result(res); // 释放结果集} else {snprintf(response, sizeof(response), "Error retrieving result");}// 发送回复信息send(task->clientfd, response, 64, 0);// 销毁任务free(task);}
}

3.主线程接收客户端连接、sql请求

int tcp_server(task_queue_t *queue) {//  初始化服务器套接字int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0) {perror("create sockfd fail\n");return -1;}struct sockaddr_in addr;memset(&addr, 0, sizeof(struct sockaddr_in));addr.sin_family = AF_INET;addr.sin_port = htons(2024);addr.sin_addr.s_addr = htonl(INADDR_ANY);if (-1 == bind(sockfd, (struct sockaddr*)&addr, sizeof(addr))) {perror("bind fail\n");return -2;}if (-1 == listen(sockfd, 5)) {perror("listen fail\n");return -3;}//IO多路复用int epfd = epoll_create(1);struct epoll_event ev;ev.events = EPOLLIN;ev.data.fd = sockfd;epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev);struct epoll_event events[1024] = {0}; while (1) {int ret = epoll_wait(epfd, events, 1024, -1);if (ret == -1) {perror("epoll_wait fail");break;}int i = 0;for (i = 0; i < ret; i++) {if (sockfd == events[i].data.fd) { struct sockaddr_in clientaddr;socklen_t len = sizeof(clientaddr);int clientfd = accept(sockfd, (struct sockaddr*)&clientaddr, &len);fcntl(clientfd, F_SETFL, SOCK_NONBLOCK);ev.events = EPOLLIN;ev.data.fd = clientfd;epoll_ctl(epfd, EPOLL_CTL_ADD, clientfd, &ev);} else if (events[i].events & EPOLLIN){while (1) {char buffer[256] = {0};int count = recv(events[i].data.fd, buffer, 10, 0);if (count < 0) {//读取完毕或当前没有数据可读或者出错if( (errno == EAGAIN) || (errno == EWOULDBLOCK)) {//读取完毕printf("recv finished\n");break;}//recv出错close(events[i].data.fd);//关闭事件的套接字break;} else if (count == 0) {//对方发送fin断开连接epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, &ev);//移除该事件close(events[i].data.fd);//关闭事件的套接字break;}else {//接收到数据task_t *task;  // 将clientfd和buffer包装进taskinit_task(task); // 初始化task的next指针strcpy(task->SQL, buffer); // 装入sql请求task->clientfd = events[i].data.fd; add_task(queue, task); // 将此task添加到任务队列} }}}}close(sockfd);return 0;
}

4.main函数

int main() {// 工作队列task_queue_t *queue = task_queue_create();if (!queue) exit(1);// 创建MySQL连接MYSQL mysqls[NUM_MYSQL_CONNECTION] = {0};int i;for (i = 0; i < NUM_MYSQL_CONNECTION; i++) {mysql_conn_init(&mysqls[i]);}// 创建工作线程pthread_t threadid[NUM_MYSQL_CONNECTION];for (i = 0; i < NUM_MYSQL_CONNECTION; i++) {struct argc *argc = (struct argc *)malloc(sizeof(struct argc));argc->mysql = &mysqls[i];argc->queue = queue;pthread_create(&threadid[i], NULL, mysql_conn_thrd_worker, argc);free(argc);}tcp_server(queue); // Tcp 服务器,接收客户端连接,包装SQL请求信息并添加到工作队列return 0;
}

推荐学习 https://xxetb.xetslk.com/s/p5Ibb

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/843692.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据面试题 —— Hive

目录 Hive 是什么为什么要使用 HiveHive 的优缺点Hive的实现逻辑&#xff0c;为什么处理小表延迟比较高你可以说一下 HQL 转换为 MR 的任务流程吗 ***你可以说一下 hive 的元数据保存在哪里吗 ***Hive与传统数据库之间的区别Hive内部表和外部表的区别 ***hive 动态分区与静态分…

Hotcoin Research | 市场洞察:2024年5月13日-5月19日

加密货币市场表现 目前&#xff0c;加密货币总市值为1.32万亿&#xff0c;BTC占比54.41%。 本周行情呈现震荡上行的态势&#xff0c;BTC在5月15日-16日&#xff0c;有一波大的拉升&#xff0c;周末为震荡行情。BTC现价为67125美元。 上涨的主要原因&#xff1a;美国4月CPI为3…

效率工作:一键为多种资产添加统一材质(小插件)

1.需求分析&#xff1a; 当导入一批资产&#xff0c;或者有同一批结构体需要添加相同材质时&#xff0c;单独为每个模型都添加材质费时费力&#xff0c;有没有什么办法&#xff0c;能同时为多个资产添加材质。 2.操作实现 1.在网上找到了一款插件&#xff0c;经过验证&#xf…

如何将天猫内容保存为PDF格式?详细步骤与实战解析

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言&#xff1a;保存天猫内容的重要性 二、环境准备与工具安装 1. 安装必要的Python包…

SpringCloud之SSO单点登录-基于Gateway和OAuth2的跨系统统一认证和鉴权详解

单点登录&#xff08;SSO&#xff09;是一种身份验证过程&#xff0c;允许用户通过一次登录访问多个系统。本文将深入解析单点登录的原理&#xff0c;并详细介绍如何在Spring Cloud环境中实现单点登录。通过具体的架构图和代码示例&#xff0c;我们将展示SSO的工作机制和优势&a…

HCIP-Datacom-ARST自选题库__BGP多选【22道题】

1.BGP认证可以防止非法路由器与BGP路由器建立邻居&#xff0c;BGP认证可以分为MD5认证和Keychain认证&#xff0c;请问以下哪些BGP报文会携带BCGP Keychain认证信息?(报头携带) open Update Notication Keepalive 2.传统的BGP-4只能管理IPv4单播路由信息&#xff0c;MP-B…

Spring-Cloud-OpenFeign源码解析-04-调用流程分析

在Spring-Cloud-OpenFeign源码解析-03-FeignClientFactoryBean分析到&#xff0c;通过Autowired或者Resource注入FeignClient实例的时候&#xff0c;实际上返回的是JDK动态代理对象&#xff0c;具体的实现逻辑在InvocationHandler的invoke方法中 回看ReflectiveFeign.newInsta…

AI大模型日报#0528:Greg专访 | 为什么OpenAI最先做出GPT-4、xAI获60亿美元融资、李飞飞经典对话Hinton

导读&#xff1a;AI大模型日报&#xff0c;爬虫LLM自动生成&#xff0c;一文览尽每日AI大模型要点资讯&#xff01;目前采用“文心一言”&#xff08;ERNIE 4.0&#xff09;、“零一万物”&#xff08;Yi-34B&#xff09;生成了今日要点以及每条资讯的摘要。欢迎阅读&#xff0…

YOLOv8/YOLOv7/YOLOv5+CRNN-车牌识别、车牌关键点定位、车牌检测(毕业设计)

目录 一、前言1、项目介绍2、图片测试效果展示 二、项目环境配置1、pytorch安装&#xff08;gpu版本和cpu版本的安装)2、pycocotools的安装3、其他包的安装 三、yolov8/yolov7/yolov5CRNN-中文车牌识别、车牌关键点定位、车牌检测算法1、yolov8算法介绍2、CRNN算法介绍3、算法流…

【加密与解密(第四版)】第十三章笔记

第十三章 HOOK技术 13.1 Hook概述 IAT HOOK&#xff08;改地址&#xff09; BOOL IAT_InstallHook(){BOOL bResult FALSE ;HMODULE hCurExe GetModuleHandle(NULL);PULONG_PTR pt ;ULONG_PTR OrginalAddr;bResult InstallModuleIATHook(hCurExe,"user32.dll",&qu…

韩顺平0基础学Java——第13天

p264-p284 安装IDEA&#xff0c;熟悉一下软件。 尴尬了&#xff0c;难道是这个版本的idea不支持jdk17&#xff0c;难受住了 成功了&#xff0c;顺便跑一下昨天的作业&#xff1a; 这都要跑2秒&#xff1f;是电脑的问题还是谁的问题&#xff1f;控制台里跑的好快的哦 设置id…

Thingsboard规则链:Message type switch节点详解

在物联网解决方案中&#xff0c;数据的高效处理与自动化决策流程是实现智能化管理的基础。Thingsboard&#xff0c;作为一个强大的开源物联网平台&#xff0c;通过其规则引擎为用户提供了一系列灵活的节点来定制复杂的业务逻辑。其中&#xff0c;Message Type Switch节点是构建…

BookxNote Pro 宝藏 PDF 笔记软件

一、简介 1、BookxNote Pro 是一款专为电子书阅读和学习笔记设计的软件&#xff0c;支持多种电子书格式&#xff0c;如PDF和EPUB&#xff0c;能够帮助用户高效地管理和阅读电子书籍&#xff0c;同时具备强大的笔记功能&#xff0c;允许用户对书籍内容进行标注、摘录和思维导图绘…

Springboot启动时报错Property ‘mapperLocations‘ was not specified.

这几天没整boot 晚上直接运行不了了 本想是在表现层写点代码测测接口的 localhost8080找半天 结果404 先考虑好久 是不是url输入错了 然后 就发现 结果boot都不能启动了 JUnit也测不出来 找了半天 结果是开关机导致数据库没开 手动打开服务 找到MySQL启动 IDEA连接数据…

ssm/springoot养老院问诊服务预约系统_96316老年人服务系统

2.管理员&#xff1a; &#xff08;1&#xff09;登入注册页面&#xff1a;管理员进行操作时需要是已注册登入的 &#xff08;2&#xff09;权限管理&#xff1a;管理员登入后可以运用权限进行相应的操作管理。 &#xff08;3&#xff09;用户管理&#xff1a;对用户进行删除、…

国产数据库替代加速 助力数字中国建设

5月24日&#xff0c;随着第七届数字中国建设峰会在福州的成功举办&#xff0c;释放数据要素价值、发展新质生产力成为当下热议的话题。 数据作为新型生产要素&#xff0c;是数字化、网络化、智能化的重要基础。北京人大金仓信息技术股份有限公司&#xff08;以下简称人大金仓&a…

OpenHarmony实战开发——宿舍全屋智能开发指南

项目说明 基于OpenAtom OpenHarmony&#xff08;以下简称“OpenHarmony”&#xff09;、数字管家开发宿舍全屋智能&#xff0c;实现碰一碰开门、碰一碰开灯、碰一碰开风扇以及烟感检测。因为各项目开发流程大体相似&#xff0c;本文主要以碰一碰开门为例介绍如何在现有OpenHar…

西储大学数据集学习

数据集下载地址&#xff1a;CWRU凯斯西储大学轴承数据数据集——附&#xff1a;下载链接_西储大学轴承数据集下载-CSDN博客 最近研究故障诊断&#xff0c;先对使用比较多的西储大学数据集研究。以资料【1】中的内容展开研究。 1、轴承的结构 轴承分为外圈、内圈、保持架和滚珠…

CC工具箱使用指南:【Word特定文本批量替换(BHM)】

一、简介 群友定制工具。 工具所要做的是批量更新Word模板中的特定文本。 输入参数为一个Word模板和Excel更新数据。 Word模板长这样&#xff1a; Word中需要更新的文本都用大括号及里内部的标签标注出来。 对应的Excel长这样&#xff1a; 第一行的标签和Word里的一一对应…

mysql 按区间统计 3 分钟维度

根据 UNIX_TIMESTAMP 去掉分钟后的的位数 思路如下select UNIX_TIMESTAMP(now()) 当前时间 秒,now() 当前时间,FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(CURRENT_TIMESTAMP) / (3 * 60)) * (3 * 60)) 3分钟为分隔去掉多余位数当前时间 秒 当前时间 3分钟为分隔去掉多余…