今天为大家说一下mysql连接池。
什么是连接池?
连接池是一种存放多个已建立连接的容器,这些连接可以被重复利用,而不必在每次使用时重新建立。 以 MySQL 连接池为例:池中事先创建了若干 MySQL 连接,当程序需要访问数据库时,直接从池中获取一个可用连接,执行完 CRUD(增删改查)操作后再放回池中。
为什么需要连接池?
在传统 PHP(FPM)模式下,每次请求都会重新与 MySQL 建立连接,用完即释放。 建立连接的过程涉及 TCP 握手、权限认证等步骤,通常需要几十毫秒甚至更多,这对高并发系统来说是性能瓶颈。
在 Swoole 中的优势
Swoole 是基于常驻内存的服务模型,程序启动后会一直运行,可以在内存中维护一个 MySQL 连接池。这样:
- 连接只需在程序启动时创建一次。
- 之后所有请求都可以直接复用连接,避免重复建立连接的开销。
- 配合协程,可以同时复用多个连接,提升并发能力。
使用连接池的好处
- 性能提升:减少频繁建立连接的时间消耗。
- 资源复用:降低 MySQL 的连接压力。
- 更稳定:避免在高并发下频繁连接/断开导致的失败率上升。
- 可控性强:可设置最大连接数,防止资源被耗尽。
具体案例
下面结合一个实际案例,介绍我在项目中是如何使用 Swoole 创建 MySQL 连接池的。
首先,我们需要用到 Swoole\Coroutine\Channel 类,它是 协程安全的通信容器,用于在协程之间传递数据。 可以简单理解为一个带容量限制的队列:当 push 或 pop 操作无法立即完成时,当前协程会挂起,调度器会去执行其他协程,从而避免阻塞整个进程。
php
$this->pool = new Channel(10);
此时 是一个空的队列、有固定容量的协程安全队列,当前元素个数为 0,容量为 10,等待读的协程队列为空,等待写的协程队列为空
接下来,我们使用 \Swoole\Coroutine\MySQL() 创建 MySQL 连接,并将它们推入连接池:
php
for ($i = 0; $i < $size; $i++) {
$mysql = new \Swoole\Coroutine\MySQL();
$res = $mysql->connect([
'host' => $config['host'],
'port' => $config['port'],
'user' => $config['username'],
'password' => $config['password'],
'database' => $config['database'],
'charset' => $config['charset'] ?? 'utf8mb4',
]);
if (!$res) {
throw new Exception("MySQL 连接失败: " . $mysql->connect_error);
}
$this->pool->push($mysql);
}
这样,一个简单的 MySQL 连接池就创建完成了(实际应用中可以将其封装成一个类)。 这里需要说明,\Swoole\Coroutine\MySQL() 本身也是协程化的 MySQL 客户端,这保证了在遇到阻塞 I/O 操作时,Swoole 可以切换到其他协程继续执行,从而提升并发性能。
使用连接时,只需从池中 pop() 一个连接,使用完后再 push() 回池中即可。
当 Swoole 服务关闭时,需要清理连接池资源,例如:
php
while (true){
$conn = $this->pool->pop(0.001);
if($conn === false) break;
$conn->close();
}
$this->pool->close();
$this->pool = null;
执行逻辑说明:
pop(0.001) 表示等待最多 1 毫秒 获取连接。如果在超时时间内没有数据,会返回 false。 这样可以避免 pop() 长时间挂起。
如果取到了连接,则调用 $conn->close() 关闭连接。
当队列为空或已关闭时,pop() 会返回 false,触发 break 跳出循环。
最后调用 <math xmlns="http://www.w3.org/1998/Math/MathML"> t h i s − > p o o l − > c l o s e ( ) 关闭队列,并将 this->pool->close() 关闭队列,并将 </math>this−>pool−>close()关闭队列,并将this->pool 置为 null。 这样可以断开 PHP 对 Channel 对象的引用,让垃圾回收器(GC)及时销毁它,避免内存泄漏。
这种做法可以确保连接池在使用完毕后被完整、及时地释放,适合在 Swoole 的长生命周期服务中使用。