webserver--7.数据库连接池

webserver--7.数据库连接池

码农世界 2024-05-19 前端 64 次浏览 0个评论

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 校验 & 数据库连接池
  • 一、头文件
  • 二、connectionRAII类
    • 1.类的定义
    • 2.构造函数与析构函数
    • 二、connection_pool类
      • 1.类的定义
      • 2.构造函数与析构函数
      • 3.GetInstance()
      • 4.init()
      • 5.GetConnection()
      • 6.ReleaseConnection()
      • 7.GetFreeConn()
      • 8.DestroyPool()
      • --------
        • 1.引入库
        • 2.读入数据
        • 总结

          校验 & 数据库连接池

          数据库连接池

          • 单例模式,保证唯一
          • list实现连接池
          • 连接池为静态大小
          • 互斥锁实现线程安全

          校验

          • HTTP请求采用POST方式
          • 登录用户名和密码校验
          • 用户注册及多线程注册安全

          共两个个class,分别是connection_pool和connectionRAII

          一、头文件

          #include 
          #include 
          #include 
          #include 
          #include 
          #include 
          #include 
          #include "../lock/locker.h"
          #include "../log/log.h"
          using namespace std;
          

          二、connectionRAII类

          • RAII(Resource Acquisition Is Initialization)即资源获取即初始化,是一种C++编程技巧,用于管理资源。connectionRAII类依托于connection_pool类,用于在函数执行期间自动申请连接和自动释放连接,避免了手动申请和释放资源出现的错误和异常情况;
          • 在创建connectionRAII对象时,它会自动调用connection_pool的GetConnection()方法来获取数据库连接;
          • 在connectionRAII对象生命周期结束时,它会自动调用connection_pool的ReleaseConnection()方法来释放数据库连接。

            1.类的定义

            class connectionRAII{
            public:
            	connectionRAII(MYSQL **con, connection_pool *connPool);
            	~connectionRAII();
            	
            private:
            	MYSQL *conRAII;
            	connection_pool *poolRAII;
            };
            

            2.构造函数与析构函数

            构造函数,用于管理MySQL数据库连接的,采用资源获取即初始化(RAII)的方式进行自动化管理

            在创建connectionRAII对象时,会自动获取一个数据库连接,并将其保存在conRAII中,同时也保存了连接池的指针,方便之后的释放操作

            // 两个参数分别是:MYSQL类型的指针SQL和connection_pool类型的指针connPool
            connectionRAII::connectionRAII(MYSQL **SQL, connection_pool *connPool){
            	*SQL = connPool->GetConnection();// 将从连接池中获取到的一个数据库连接赋值给SQL指向的内存空间
            	
            	conRAII = *SQL;// 将SQL所指向的内存空间的内容赋值给了conRAII成员变量
            	poolRAII = connPool;// 将connPool所指向的内存空间的内容赋值给了poolRAII成员变量
            }
            

            析构函数,用于释放数据库连接资源。在connectionRAII对象被销毁时(例如,作用域结束或delete运算符调用),会自动调用该析构函数

            在connectionRAII对象被销毁时,会自动释放其所持有的数据库连接,避免了内存泄漏等问题。同时,由于使用了connection pool,还可以提高程序的效率,避免频繁创建和销毁数据库连接带来的开销

            connectionRAII::~connectionRAII(){
            	poolRAII->ReleaseConnection(conRAII);
            }
            

            二、connection_pool类

            • 维护一个MySQL连接池,提供获取和释放连接的方法;
            • 可以初始化连接池参数,包括URL、用户名、密码、数据库名、端口号、最大连接数等;
            • 实现了单例模式,确保只有一个连接池实例存在;
            • 通过使用锁和信号量控制并发访问连接池的线程安全问题。

              1.类的定义

              class connection_pool
              {
              public:
              	MYSQL *GetConnection();				 //获取数据库连接
              	bool ReleaseConnection(MYSQL *conn); //释放连接
              	int GetFreeConn();					 //获取连接
              	void DestroyPool();					 //销毁所有连接
              	//单例模式
              	static connection_pool *GetInstance();
              	void init(string url, string User, string PassWord, string DataBaseName, int Port, int MaxConn, int close_log); 
              private:
              	connection_pool();
              	~connection_pool();
              	int m_MaxConn;  //最大连接数
              	int m_CurConn;  //当前已使用的连接数
              	int m_FreeConn; //当前空闲的连接数
              	locker lock;
              	list connList; //连接池
              	sem reserve;
              public:
              	string m_url;			 //主机地址
              	string m_Port;		 //数据库端口号
              	string m_User;		 //登陆数据库用户名
              	string m_PassWord;	 //登陆数据库密码
              	string m_DatabaseName; //使用数据库名
              	int m_close_log;	//日志开关
              };
              

              2.构造函数与析构函数

              构造函数,成员变量m_CurConn和m_FreeConn被初始化为0

              connection_pool::connection_pool()
              {
              	m_CurConn = 0; //当前已使用的连接数
              	m_FreeConn = 0; //当前空闲的连接数
              }
              

              析构函数,对连接池进行释放

              connection_pool::~connection_pool()
              {
              	DestroyPool();
              }
              

              3.GetInstance()

              在整个应用程序中,只需要调用GetInstance()方法获取该连接池的唯一实例,然后就可以使用该实例执行数据库操作

              connection_pool *connection_pool::GetInstance()
              {
              	// static确保整个应用程序中只有一个数据库连接池
              	static connection_pool connPool;
              	return &connPool;
              }
              

              4.init()

              用于初始化连接池

              在整个程序生命周期中,只需要调用一次init()函数,就可以初始化连接池,然后在需要访问数据库时,从连接池中获取连接,执行完操作后,将连接归还到连接池中以供下次使用

              void connection_pool::init(string url, string User, string PassWord, string DBName, int Port, int MaxConn, int close_log)
              {
              	// 将传入参数赋值给成员变量
              	m_url = url;
              	m_Port = Port;
              	m_User = User;
              	m_PassWord = PassWord;
              	m_DatabaseName = DBName;
              	m_close_log = close_log;
              	// 创建了指定数量的数据库连接,并将连接添加到connList列表中
              	for (int i = 0; i < MaxConn; i++)
              	{
              		MYSQL *con = NULL;
              		con = mysql_init(con);
              		// 如果连接创建失败,则会输出错误信息并立即退出程序
              		if (con == NULL)
              		{
              			LOG_ERROR("MySQL Error");
              			exit(1);
              		}
              		// 创建mysql连接
              		con = mysql_real_connect(con, url.c_str(), User.c_str(), PassWord.c_str(), DBName.c_str(), Port, NULL, 0);
              		// 如果连接创建失败,则会输出错误信息并立即退出程序
              		if (con == NULL)
              		{
              			LOG_ERROR("MySQL Error");
              			exit(1);
              		}
              		// 如果成功创建连接,则将连接添加到connList列表中
              		connList.push_back(con);
              		// 并将m_FreeConn计数器加1,表示新增一个可用连接
              		++m_FreeConn;
              	}
              	// 创建了一个名为reserve的信号量,初始值为m_FreeConn,表示当前空闲连接数
              	reserve = sem(m_FreeConn);
              	// m_MaxConn变量被设置为m_FreeConn,表示最大连接数也是当前可用连接数
              	m_MaxConn = m_FreeConn;
              }
              

              5.GetConnection()

              数据库连接池中获取可用连接的函数。当有请求时,它会从数据库连接池(connList)中返回一个可用连接(con),并更新使用和空闲连接数

              //当有请求时,从数据库连接池中返回一个可用连接,更新使用和空闲连接数
              MYSQL *connection_pool::GetConnection()
              {
              	MYSQL *con = NULL;
              	// 检查连接池中是否有可用连接,如果没有则返回NULL表示没有可用连接
              	if (0 == connList.size())
              		return NULL;
              	// 在没有可用连接的情况下会将线程阻塞以等待可用连接
              	reserve.wait();
              	
              	lock.lock();
              	// 从连接池的头部取出一个连接
              	con = connList.front();
              	// 同时从连接池中移除该连接
              	connList.pop_front();
              	// 更新连接池中的空闲和正在使用的连接数
              	--m_FreeConn;
              	++m_CurConn;
              	lock.unlock();
              	// 返回获取到的可用连接
              	return con;
              }
              

              6.ReleaseConnection()

              释放当前使用的连接

              数据库连接池中释放连接的函数。当使用完一个连接后,可以通过调用该函数将该连接释放回连接池,并更新使用和空闲连接数

              bool connection_pool::ReleaseConnection(MYSQL *con)
              {
              	// 检查传入的参数con是否为空指针,如果是则直接返回false表示释放失败
              	if (NULL == con)
              		return false;
              	lock.lock();
              	// 将连接con添加到连接池的尾部
              	connList.push_back(con);
              	// 更新连接池中的空闲和正在使用的连接数
              	++m_FreeConn;
              	--m_CurConn;
              	lock.unlock();
              	// 调用reserve.post()方法,这个方法会通知之前被阻塞的线程,告诉它们当前有可用连接了,以便它们能够从连接池中获取连接
              	reserve.post();
              	return true;
              }
              

              7.GetFreeConn()

              返回当前空闲的连接数

              数据库连接池中获取当前空闲连接数的函数。它直接返回连接池对象中的m_FreeConn成员变量,该变量记录了当前连接池中的空闲连接数量

              int connection_pool::GetFreeConn()
              {
              	return this->m_FreeConn;
              }
              

              8.DestroyPool()

              销毁数据库连接池

              数据库连接池中销毁连接池的函数。当不再需要使用连接池时,可以通过调用该函数来销毁连接池,并释放已分配的资源

              void connection_pool::DestroyPool()
              {
              	lock.lock();
              	// 检查连接池中是否还有连接
              	if (connList.size() > 0)
              	{
              		list::iterator it;
              		// 遍历所有连接并调用mysql_close()方法关闭连接,释放资源
              		for (it = connList.begin(); it != connList.end(); ++it)
              		{
              			MYSQL *con = *it;
              			mysql_close(con);
              		}
              		// 将连接池中的m_CurConn和m_FreeConn成员变量都置为0,表示当前没有任何连接在使用或者空闲
              		m_CurConn = 0;
              		m_FreeConn = 0;
              		// 调用connList.clear()方法清空连接池中的连接列表
              		connList.clear();
              	}
              	lock.unlock();
              }
              

              --------

              1.引入库

              代码如下(示例):

               
              

              2.读入数据

              代码如下(示例):

              data = pd.read_csv(
                  'https://labfile.oss.aliyuncs.com/courses/1283/adult.data.csv')
              print(data.head())
              

              该处使用的url网络请求的数据。


              总结

              提示:这里对文章进行总结:

              例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

转载请注明来自码农世界,本文标题:《webserver--7.数据库连接池》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,64人围观)参与讨论

还没有评论,来说两句吧...

Top