当前位置: 首页 > news >正文

PHP数据库Connection与Statement池化

PHP数据库Connection与Statement池化

数据库连接池和Statement池化可以显著提升数据库密集型应用的性能。连接池复用TCP连接,Statement池化复用SQL执行计划。今天说说PHP中的池化技术。

连接池的核心是预先创建一批连接,使用时获取,使用后归还。

```php
class PdoConnectionPool
{
private array $pool = [];
private int $maxSize;
private int $currentSize = 0;
private string $dsn;
private string $user;
private string $pass;
private array $options;

public function __construct(string $dsn, string $user, string $pass, int $maxSize = 10, array $options = [])
{
$this->dsn = $dsn;
$this->user = $user;
$this->pass = $pass;
$this->maxSize = $maxSize;
$this->options = $options;
}

public function get(): PDO
{
// 从池中获取可用连接
foreach ($this->pool as $key => $connection) {
if (!$connection['in_use']) {
if ($this->isHealthy($connection['pdo'])) {
$this->pool[$key]['in_use'] = true;
$this->pool[$key]['last_used'] = time();
return $connection['pdo'];
}
unset($this->pool[$key]);
$this->currentSize--;
}
}

// 创建新连接
if ($this->currentSize < $this->maxSize) {
$pdo = $this->createConnection();
$this->pool[] = [
'pdo' => $pdo,
'in_use' => true,
'created_at' => time(),
'last_used' => time(),
];
$this->currentSize++;
return $pdo;
}

// 等待连接释放
$waitTime = 0;
while ($waitTime < 5000) {
foreach ($this->pool as $key => $connection) {
if (!$connection['in_use']) {
if ($this->isHealthy($connection['pdo'])) {
$this->pool[$key]['in_use'] = true;
$this->pool[$key]['last_used'] = time();
return $connection['pdo'];
}
unset($this->pool[$key]);
$this->currentSize--;
}
}
usleep(200);
$waitTime += 200;
}

throw new \RuntimeException("连接池已满,等待超时");
}

public function release(PDO $pdo): void
{
foreach ($this->pool as $key => $connection) {
if ($connection['pdo'] === $pdo) {
$this->pool[$key]['in_use'] = false;
return;
}
}
}

public function closeAll(): void
{
foreach ($this->pool as $connection) {
$connection['pdo'] = null;
}
$this->pool = [];
$this->currentSize = 0;
}

public function status(): array
{
$inUse = 0;
foreach ($this->pool as $conn) {
if ($conn['in_use']) $inUse++;
}

return [
'total' => $this->currentSize,
'in_use' => $inUse,
'idle' => $this->currentSize - $inUse,
'max' => $this->maxSize,
];
}

private function createConnection(): PDO
{
return new PDO($this->dsn, $this->user, $this->pass, $this->options + [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
}

private function isHealthy(PDO $pdo): bool
{
try {
$pdo->query('SELECT 1');
return true;
} catch (\Exception $e) {
return false;
}
}

public function __destruct()
{
$this->closeAll();
}
}

class PooledDatabase
{
private PdoConnectionPool $pool;

public function __construct(PdoConnectionPool $pool)
{
$this->pool = $pool;
}

public function query(string $sql, array $params = []): array
{
$pdo = $this->pool->get();
try {
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
return $stmt->fetchAll();
} finally {
$this->pool->release($pdo);
}
}

public function execute(string $sql, array $params = []): int
{
$pdo = $this->pool->get();
try {
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
return $stmt->rowCount();
} finally {
$this->pool->release($pdo);
}
}
}
?>

Statement池化可以避免重复解析SQL:

```php
class StatementPool
{
private array $statements = [];
private PdoConnectionPool $pool;

public function __construct(PdoConnectionPool $pool)
{
$this->pool = $pool;
}

public function execute(string $sql, array $params = []): array
{
$hash = md5($sql);

if (!isset($this->statements[$hash])) {
$pdo = $this->pool->get();
try {
$this->statements[$hash] = [
'statement' => $pdo->prepare($sql),
'pdo' => $pdo,
];
} finally {
$this->pool->release($pdo);
}
}

$this->statements[$hash]['statement']->execute($params);
return $this->statements[$hash]['statement']->fetchAll();
}
}
?>

池化技术的关键是资源复用和健康检查。连接池减少TCP握手的开销,Statement池化减少SQL解析的次数。在Swoole等常驻内存环境中,池化的效果更明显。但在PHP-FPM中,每个请求结束后连接就释放了,池化的意义不大

http://www.jsqmd.com/news/941579/

相关文章:

  • 南宁黄金回收全攻略:实测四大靠谱商家,手把手教你避开所有“坑”! - 行行星
  • 云计算与大数据在农业气候风险评估中的应用实践
  • 黑马复盘 -- 优惠券秒杀
  • Mathtype 7.0安装后Word闪退?可能是6.9的‘幽灵文件’在捣乱(Win10/64位避坑指南)
  • 别再只调参了!从U-Net的‘跳跃连接’入手,聊聊如何用注意力机制(如CBAM)提升你的医学图像分割精度
  • 银行的 STG 缓冲层(Stage Layer)、数据备份、数据脱敏
  • 2026年西藏钢结构工程材料采购守则:源头工厂直供与物流保障完全剖析 - 企业名录优选推荐
  • 2026彭祖蜜深度测评:如何为健康饮品匹配最佳方案? - 资讯纵览
  • OFDM与OTFS信号智能识别工具:含多SNR实测数据集及可直接运行的CNN/Transformer模型
  • SWT桌面应用专用图表库:轻量Java组件,支持线图/柱状图/散点图等10余种交互式图表
  • 从工厂车间到智能家居:STM32F4 IAP升级的两种物理层实战(RS485 vs RS232)全解析
  • 别再乱装字体了!手把手教你用FontForge和Python批量检查字体版权与字符集
  • 告别分区烦恼!用Ventoy+VMware把Ubuntu塞进U盘,一个.vtoy文件走天下
  • 5分钟掌握BepInEx:让Unity游戏焕然一新的终极插件框架
  • 2025年Q3国内高纯石英砂优质供应商精选 - 安互工业信息
  • Scarab模组管理器:让空洞骑士模组安装变得前所未有的简单
  • 2026基坑气膜生产厂家哪家好?依托行业规范,高性价比基坑气膜生产厂家推荐 - 商业新知
  • Redis 入门必学:List 列表类型完全指南
  • Ubuntu登录界面黑屏?手把手教你用lightdm --debug排查‘Failed to Start Light Display Manager’
  • VLC for Android 架构深度解析:跨平台媒体播放器完整技术实现指南
  • VC++多线程Modbus RTU串口调试工具(含完整MFC界面与串口封装)
  • 哈尔滨黄金回收人气榜本地论坛票选,得票最高的竟是这家 - 奢侈品回收测评
  • Unraid新手必看:从群晖迁移到Unraid,我的磁盘阵列、SMB共享与权限设置心得
  • NHSE:5个核心功能解锁你的动森岛屿无限可能
  • 微软研究院教师奖学金:如何为青年学者提供科研自由与创新土壤
  • 智能自动化抢票解决方案:告别手动抢票的95%成功率技术方案
  • 2026年Q2高纯石英砂供应商精选榜单 - 安互工业信息
  • 基于Cortana与本地中间件构建智能学术研究助手:从语音交互到工作流自动化
  • 从“灵光一现”到“民主投票”:Self-Consistency如何改变了我们使用ChatGPT的方式?
  • AI模型注册不是加个API那么简单:12项核心元数据规范+8类自动化校验规则全披露