webserver--7.数据库连接池


校验 & 数据库连接池

数据库连接池

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

校验

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

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

一、头文件

#include <stdio.h>
#include <list>
#include <mysql/mysql.h>
#include <error.h>
#include <string.h>
#include <iostream>
#include <string>
#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<MYSQL *> 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<MYSQL *>::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提供了大量能使我们快速便捷地处理数据的函数和方法。

  • 37
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要配置SQLSugar连接池连接数据库,可以按照以下步骤操作: 1. 在.NET Core Web Api项目中安装SQLSugar NuGet包。 2. 在appsettings.json文件中添加数据库连接字符串,例如: ``` "ConnectionStrings": { "DefaultConnection": "Server=localhost;Database=mydatabase;User Id=myuser;Password=mypassword;" } ``` 3. 在Startup.cs文件中添加SQLSugar连接池服务配置: ```csharp using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using SqlSugar; public class Startup { private readonly IConfiguration _config; public Startup(IConfiguration config) { _config = config; } public void ConfigureServices(IServiceCollection services) { // 配置SQLSugar连接池 services.AddScoped<ISqlSugarClient>(provider => { var connectionString = _config.GetConnectionString("DefaultConnection"); var db = new SqlSugarClient(new ConnectionConfig() { ConnectionString = connectionString, DbType = DbType.MySql, // 数据库类型 IsAutoCloseConnection = true, // 自动释放连接 InitKeyType = InitKeyType.Attribute // 实体定义方式 }); return db; }); // 其他服务配置... } } ``` 4. 在控制器中注入ISqlSugarClient服务,并使用它来访问数据库。 ```csharp using Microsoft.AspNetCore.Mvc; using SqlSugar; [ApiController] [Route("[controller]")] public class MyController : ControllerBase { private readonly ISqlSugarClient _db; public MyController(ISqlSugarClient db) { _db = db; } [HttpGet] public IActionResult Get() { var list = _db.Queryable<MyEntity>().ToList(); return Ok(list); } } ``` 这样就可以使用SQLSugar连接池来连接数据库了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值