440
社区成员




MySQL 连接池本质上是一个数据库连接的缓存容器。
2.1 提高性能:通过复用连接池中的连接,避免了重复的连接创建过程,大大缩短了数据库操作的响应时间,在高并发场景下,显著提升了系统的整体性能。
2.2 减少资源浪费:不再频繁创建和销毁连接,降低了系统资源的消耗。
2.3 提升应用稳定性:连接池可以对连接进行统一管理,当出现连接泄漏(即应用程序获取连接后未正确归还)等问题时,连接池能够进行一定程度的检测和处理,避免因连接问题导致应用程序崩溃,从而提升了应用的稳定性。
它在系统初始化时创建一定数量的数据库连接对象,并将这些连接维护在一个池中。当应用程序需要与 MySQL 数据库进行交互时,无需重新创建新的连接,而是从连接池中获取一个已有的连接;当操作完成后,再将该连接归还到连接池中,以便后续其他请求复用。这种方式大大减少了连接创建和销毁的开销。
4.1 获取返回值
同步链接(Synchronous): 通过接口的返回值接受数据库返回值,主线程会堵塞。
异步连接(Asynchronous): 通过回调函数接受数据库返回值,主线程不会堵塞。
4.2连接流程
同步 异步
4.3使用场景
4.3.1同步连接池
1.配置加载:配置文件写入,系统文件。
2.数据初始化:热点数据加载,避免数据库重复访问。
3.服务器初始化:服务器主线程初始化。
4.3.2异步连接池
服务器正常启动后,各种操作,耗时查询。
libmysqlclient //纯c实现
libmysqlcppconn //c++实现,使用了异常机制
//阻塞io
7.1安装接口库
//安装 libmysqlcppconn
sudo apt-get install libmysqlcppconn-dev
**头文件: /usr/include/cppconn/*.h
**库文件: /uer/lib/x86_64-linux-gnu/
libmysqlcppconn.a
libmysqlcppconn.so
7.2 异步连接
基于连接去执行命令(send)和等待结果(recv)的过程是一个耗时操作,考虑使用线程池去实现。
因为线程要获取,命令的返回值结果作为执行命令的参数,所以我们引入future-promise,来获取结果
主线程创建 promise 并获取 future。
新线程执行 database_query(),查询完成后调用 prom.set_value(result) 传递查询结果。
主线程阻塞等待 fut.get() 获取 SQL 查询结果
7.3代码实现
//MySQLConnPool.h
namespace sql {
class ResultSet;
}
//前置声明 防止依赖过深
class MySQLConn;
template <typename T>
class BlockingQueue;
class SQLOperation;
class MySQLConnPool {
public:
//获取单例
static MySQLConnPool *GetInstance(const std::string &db);
void InitPool(const std::string &url, int pool_size);
//输入sql语句,执行对应的回调函数
QueryCallback Query(const std::string &sql, std::function<void(std::unique_ptr<sql::ResultSet>)> &&cb);
private:
MySQLConnPool(const std::string &db) : database_(db) {}
~MySQLConnPool();
std::string database_;
std::vector<MySQLConn *> pool_;
//因为数据库有多个,但是我们每次只访问一个,所以用单例模式
//一个数据库对应一个单例,所以用unordered_map存储
static std::unordered_map<std::string, MySQLConnPool *> instances_;
//阻塞队列 存储sql操作
BlockingQueue<SQLOperation *> *task_queue_;
};
//MySQLConn.h
//前置声明
namespace sql
{
class Driver;
class Connection;
class SQLException;
class ResultSet;
}
class MySQLWorker;
template <typename T>
class BlockingQueue;
class SQLOperation;
struct MySQLConnInfo {
explicit MySQLConnInfo(const std::string &info, const std::string &db);
std::string user;
std::string password;
std::string database;
std::string url;
};
class MySQLConn {
public:
MySQLConn(const std::string &info, const std::string &db, BlockingQueue<SQLOperation *> &task_queue);
~MySQLConn();
//自定义 连接函数,防止连接中断
int Open();
void Close();
//执行sql语句
sql::ResultSet* Query(const std::string &sql);
private:
//异常处理函数
void HandlerException(sql::SQLException &e);
//sql驱动,连接
sql::Driver *driver_;
sql::Connection *conn_;
//对应的线程对象
MySQLWorker *worker_;
MySQLConnInfo info_;
};
//MySQLWorker.h
class MySQLConn;
template <typename T>
class BlockingQueue;
class SQLOperation;
class MySQLWorker {
public:
//传入连接线程,和执行命令队列
MySQLWorker(MySQLConn *conn, BlockingQueue<SQLOperation *> &task_queue);
~MySQLWorker();
void Start();
void Stop();
private:
//工作线程
void Worker();
MySQLConn *conn_;
std::thread worker_;
//任务队列
BlockingQueue<SQLOperation *> &task_queue_;
};
//SQLOperation.h
namespace sql
{
class ResultSet;
}
class MySQLConn;
class SQLOperation {
public:
explicit SQLOperation(const std::string &sql) : sql_(sql) {}
void Execute(MySQLConn *conn);
std::future<std::unique_ptr<sql::ResultSet>> GetFuture() {
return promise_.get_future();
}
private:
std::string sql_;
std::promise<std::unique_ptr<sql::ResultSet>> promise_;
};
//QueryCallback.h
namespace sql
{
class ResultSet;
}
class QueryCallback {
public:
QueryCallback(std::future<std::unique_ptr<sql::ResultSet>> &&future, std::function<void(std::unique_ptr<sql::ResultSet>)> &&cb)
: future_(std::move(future)), cb_(std::move(cb))
{
}
bool InvokeIfReady() {
if (future_.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
cb_(std::move(future_.get()));
return true;
}
return false;
}
private:
std::future<std::unique_ptr<sql::ResultSet>> future_;
std::function<void(std::unique_ptr<sql::ResultSet>)> cb_;
};
//AsyncProcessor.h
class QueryCallback;
class AsyncProcessor
{
public:
void AddQueryCallback(QueryCallback &&query_callback);
void InvokeIfReady();
private:
std::vector<QueryCallback> pending_queries_;
};