目录
1.基本概念
数据库连接池是在多用户环境中管理数据库连接的有效机制,特别是对于高并发应用。它通过在应用启动时预先创建一定数量的数据库连接,并将这些连接保存在一个“池”中,从而允许应用程序在需要时迅速获取已经建立的连接。这样,每次数据库操作不需要重新经历建立和断开连接的整个过程,大大提高了效率和响应速度。下面详细介绍使用数据库连接池与直接管理数据库连接的区别,以及连接池的工作流程:
1.1不使用连接池的流程
- 通过三次握手建立TCP连接:客户端和服务器之间的每个新的数据库请求都需要通过网络进行三次握手,这是建立TCP连接的标准过程。
- MySQL认证:建立TCP连接后,客户端需要进行MySQL认证,包括发送登录凭据(如用户名和密码),服务器验证后才能允许操作。
- SQL执行:认证通过后,客户端可以执行SQL语句进行数据查询或修改。
- 通过四次挥手断开TCP连接:数据传输完成后,客户端和服务器将通过四次挥手的方式断开TCP连接,释放网络资源。
1.2使用连接池的流程
- 初始化连接池:在应用程序启动时,连接池根据配置参数预先创建一定数量的数据库连接。这些连接已经完成了TCP的三次握手和MySQL认证。
- 获取连接:当应用程序需要访问数据库时,直接从连接池中获取一个已经建立并认证的连接,省去了连接建立和认证的时间。
- 使用连接:应用程序使用获取到的连接执行所需的SQL操作。这期间,连接被认为是“繁忙”状态。
- 释放连接:操作完成后,不是断开连接,而是将连接归还到连接池,标记为“空闲”状态,可供其他操作重用。
- 维护连接:连接池会管理连接的生命周期,包括验证连接的有效性、处理超时连接、按需创建或关闭连接等,以确保连接池的健康和响应性。
1.3好处
- 资源复用:通过重用已经建立和认证的连接,减少了频繁进行TCP连接建立(三次握手)和断开(四次挥手)的开销。
- 提高响应速度:连接已预建立,应用程序可以几乎即刻获得数据库连接,显著提高响应速度。
- 更好的并发处理能力:连接池能够有效管理多个连接,支持更高的并发请求,提高应用性能。
- 增强的连接管理功能:现代连接池提供高级功能,如自动恢复无效连接,提供连接的健康检查,增强应用的稳定性和可靠性。
- 可配置性和灵活性:连接池参数(如池大小、连接超时等)可配置,允许灵活应对不同的应用场景和负载条件。
通过这种机制,数据库连接池不仅提高了数据库操作的效率,还增加了系统的可靠性和稳定性,是处理大规模并发数据库交互的理想选择。
2.同步连接池/异步连接池
2.1同步连接池
2.1.1运行机理:
同步连接池维护一组数据库连接,并在用户请求时直接分配这些连接。这种模式下,连接池通常限制了同时活跃的最大线程数,确保系统资源的合理利用。每个线程从池中获取一个连接,直到执行完毕后再将其释放回池中。这种方式简单直接,用户请求和数据库应答之间没有异步处理,线程在执行数据库操作期间会保持阻塞状态,直到数据库操作完成。
加锁是为了让每个连接只有一个线程处理。
2.1.2代码
直接拿到数据库返回结果。
template <class T>
QueryResult DatabaseWorkerPool<T>::Query(char const* sql, T* connection /*= nullptr*/)
{
if (!connection)
connection = GetFreeConnection();
ResultSet* result = connection->Query(sql); //调用了mysql_query
connection->Unlock();
if (!result || !result->GetRowCount() || !result->NextRow())
{
delete result;
return QueryResult(nullptr);
}
return QueryResult(result);
}
2.1.3使用场景:(初始化)
- 服务器初始化:在服务器启动时,可以并行地开启多个线程来初始化数据,每个线程使用连接池中的一个连接,这样可以显著加快初始化流程。
- 高效的事务处理:对于需要快速完成并确保数据一致性的业务操作,同步处理可以简化逻辑并减少错误处理的复杂性。
2.2异步连接池
2.2.1运行机理:
异步连接池允许应用程序在不同的线程中发起数据库请求,而不需要等待数据库操作完成。用户的请求会通过一个异步接口发送到数据库,连接池管理着这些请求,并允许它们在数据库层面并行执行。当数据库操作完成后,结果会通过回调函数或者Future/Promise对象返回给主线程,主线程此时可以继续处理其他任务,而不会被阻塞。
2.1.2代码
AsyncQuery创建了一个task,并将task入队列,并不是立马获取到返回结果,而是在其他线程中获取。
template <class T>
QueryCallback DatabaseWorkerPool<T>::AsyncQuery(char const* sql)
{
BasicStatementTask* task = new BasicStatementTask(sql, true);
// Store future result before enqueueing - task might get already processed and deleted before returning from this method
QueryResultFuture result = task->GetFuture();
Enqueue(task);
return QueryCallback(std::move(result));
}
2.2.3使用场景:(业务)
- 非阻塞I/O模型:适用于I/O密集型应用,如Web服务器或网络应用,其中核心线程需要维持轻量,快速响应外部请求,不应被数据库操作阻塞。
- 高并发请求处理:在处理大量并发请求时,异步连接池可以使数据库操作的等待时间不阻塞主业务逻辑,提高整体应用的吞吐量。