首页
4K壁纸
直播
统计分析
友情链接
搜索
1
#1031 – TABLE STORAGE ENGINE FOR ” DOESN’T HAVE THIS OPTION解决方法
1,224 阅读
2
让浏览器不显示 https 页面中 http 请求警报 http-equiv=”Content-Security-Policy” content=”upgrade-insecure-requests”
941 阅读
3
报错代码:ERROR 1227 (42000)-解决办法
731 阅读
4
微信个人商户号养号建议
581 阅读
5
解决移动端position:fixed随软键盘移动的问题
551 阅读
Php
Mysql
Linux
Reids
Java
Python
常用笔记
学习
乱七八糟
Search
标签搜索
php
Mysql
千卡云支付
Linux
redis
千卡云
千卡易支付
Nginx
function
JS
shell
JSON
跨域
支付宝
CentOS
Apache
支付
composer
Array
database
蓝科迪梦
累计撰写
102
篇文章
累计收到
0
条评论
首页
栏目
Php
Mysql
Linux
Reids
Java
Python
常用笔记
学习
乱七八糟
页面
4K壁纸
直播
统计分析
友情链接
搜索到
1
篇与
的结果
2025-10-19
数据库连接池与性能优化
PHP开发中的复杂问题及解决方案:数据库连接池与性能优化在高并发的PHP应用中,数据库连接管理是一个关键性能瓶颈。频繁创建和销毁数据库连接会消耗大量系统资源,影响应用响应速度和吞吐量。常见的数据库连接问题1. 连接泄漏// 忘记关闭数据库连接导致连接泄漏 $pdo = new PDO($dsn, $username, $password); $result = $pdo->query("SELECT * FROM users"); // 连接未正确关闭2. 连接数超限// 每次请求都创建新连接,快速耗尽数据库连接数 for ($i = 0; $i < 100; $i++) { $pdo = new PDO($dsn, $username, $password); // 处理业务逻辑 }解决方案方案一:基础连接池实现<?php /** * 数据库连接池管理器 */ class DatabaseConnectionPool { private static ?self $instance = null; private array $connections = []; private array $usedConnections = []; private int $maxConnections; private int $currentConnections = 0; private array $config; private function __construct(array $config, int $maxConnections = 20) { $this->config = $config; $this->maxConnections = $maxConnections; // 注册关闭回调 register_shutdown_function([$this, 'closeAllConnections']); } /** * 获取连接池单例实例 */ public static function getInstance(array $config = [], int $maxConnections = 20): self { if (self::$instance === null) { self::$instance = new self($config, $maxConnections); } return self::$instance; } /** * 获取数据库连接 */ public function getConnection(): PDO { // 检查是否有可用的空闲连接 if (!empty($this->connections)) { $connection = array_pop($this->connections); $this->usedConnections[spl_object_hash($connection)] = $connection; return $connection; } // 检查是否可以创建新连接 if ($this->currentConnections < $this->maxConnections) { $connection = $this->createConnection(); $this->usedConnections[spl_object_hash($connection)] = $connection; $this->currentConnections++; return $connection; } // 等待可用连接(简化实现) throw new Exception("No available database connections"); } /** * 释放连接回连接池 */ public function releaseConnection(PDO $connection): void { $hash = spl_object_hash($connection); if (isset($this->usedConnections[$hash])) { unset($this->usedConnections[$hash]); $this->connections[] = $connection; } } /** * 创建新的数据库连接 */ private function createConnection(): PDO { $dsn = $this->config['dsn'] ?? ''; $username = $this->config['username'] ?? ''; $password = $this->config['password'] ?? ''; $options = $this->config['options'] ?? [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]; return new PDO($dsn, $username, $password, $options); } /** * 关闭所有连接 */ public function closeAllConnections(): void { foreach ($this->connections as $connection) { $connection = null; } foreach ($this->usedConnections as $connection) { $connection = null; } $this->connections = []; $this->usedConnections = []; $this->currentConnections = 0; } /** * 获取连接池状态 */ public function getPoolStatus(): array { return [ 'total_connections' => $this->currentConnections, 'available_connections' => count($this->connections), 'used_connections' => count($this->usedConnections), 'max_connections' => $this->maxConnections ]; } }方案二:高级连接池with健康检查<?php /** * 带健康检查的高级连接池 */ class AdvancedConnectionPool { private array $connections = []; private array $usedConnections = []; private int $maxConnections; private int $minConnections; private array $config; private int $connectionTimeout; private int $idleTimeout; public function __construct( array $config, int $maxConnections = 50, int $minConnections = 5, int $connectionTimeout = 30, int $idleTimeout = 300 ) { $this->config = $config; $this->maxConnections = $maxConnections; $this->minConnections = $minConnections; $this->connectionTimeout = $connectionTimeout; $this->idleTimeout = $idleTimeout; // 初始化最小连接数 $this->initializeMinConnections(); // 注册定时清理任务 $this->registerCleanupTask(); } /** * 初始化最小连接数 */ private function initializeMinConnections(): void { for ($i = 0; $i < $this->minConnections; $i++) { try { $connection = $this->createConnection(); $this->connections[] = [ 'connection' => $connection, 'last_used' => time(), 'created_at' => time() ]; } catch (Exception $e) { error_log("Failed to initialize connection: " . $e->getMessage()); } } } /** * 获取数据库连接 */ public function getConnection(): PDO { // 清理过期连接 $this->cleanupIdleConnections(); // 查找可用连接 $connection = $this->findAvailableConnection(); if ($connection !== null) { return $connection; } // 创建新连接 if (count($this->usedConnections) + count($this->connections) < $this->maxConnections) { return $this->createNewConnection(); } // 等待可用连接 return $this->waitForAvailableConnection(); } /** * 查找可用连接 */ private function findAvailableConnection(): ?PDO { while (!empty($this->connections)) { $connInfo = array_pop($this->connections); // 检查连接是否仍然有效 if ($this->isConnectionValid($connInfo['connection'])) { $connInfo['last_used'] = time(); $this->usedConnections[spl_object_hash($connInfo['connection'])] = $connInfo; return $connInfo['connection']; } else { // 连接无效,丢弃 $connInfo['connection'] = null; } } return null; } /** * 创建新连接 */ private function createNewConnection(): PDO { $connection = $this->createConnection(); $connInfo = [ 'connection' => $connection, 'last_used' => time(), 'created_at' => time() ]; $this->usedConnections[spl_object_hash($connection)] = $connInfo; return $connection; } /** * 等待可用连接 */ private function waitForAvailableConnection(): PDO { $startTime = time(); while (time() - $startTime < $this->connectionTimeout) { usleep(100000); // 等待100ms $connection = $this->findAvailableConnection(); if ($connection !== null) { return $connection; } } throw new Exception("Timeout waiting for database connection"); } /** * 检查连接是否有效 */ private function isConnectionValid(PDO $connection): bool { try { $connection->query("SELECT 1"); return true; } catch (Exception $e) { return false; } } /** * 释放连接 */ public function releaseConnection(PDO $connection): void { $hash = spl_object_hash($connection); if (isset($this->usedConnections[$hash])) { $connInfo = $this->usedConnections[$hash]; $connInfo['last_used'] = time(); $this->connections[] = $connInfo; unset($this->usedConnections[$hash]); } } /** * 清理空闲连接 */ private function cleanupIdleConnections(): void { $currentTime = time(); $remainingConnections = []; foreach ($this->connections as $connInfo) { // 保留最近使用的连接和最小连接数要求的连接 if (($currentTime - $connInfo['last_used']) < $this->idleTimeout || (count($remainingConnections) + count($this->usedConnections)) < $this->minConnections) { $remainingConnections[] = $connInfo; } else { // 关闭超时连接 $connInfo['connection'] = null; } } $this->connections = $remainingConnections; } /** * 注册清理任务 */ private function registerCleanupTask(): void { // 在应用关闭时清理连接 register_shutdown_function([$this, 'shutdown']); } /** * 应用关闭时的清理工作 */ public function shutdown(): void { foreach ($this->connections as $connInfo) { $connInfo['connection'] = null; } foreach ($this->usedConnections as $connInfo) { $connInfo['connection'] = null; } } /** * 创建数据库连接 */ private function createConnection(): PDO { $options = $this->config['options'] ?? [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_PERSISTENT => false // 不使用持久连接,由连接池管理 ]; return new PDO( $this->config['dsn'], $this->config['username'], $this->config['password'], $options ); } }方案三:连接池使用封装<?php /** * 数据库操作封装类 */ class DatabaseManager { private AdvancedConnectionPool $connectionPool; private static ?self $instance = null; private function __construct() { $config = [ 'dsn' => $_ENV['DATABASE_DSN'] ?? 'mysql:host=localhost;dbname=test', 'username' => $_ENV['DATABASE_USER'] ?? 'root', 'password' => $_ENV['DATABASE_PASS'] ?? '', 'options' => [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ] ]; $this->connectionPool = new AdvancedConnectionPool( $config, maxConnections: (int)($_ENV['DB_MAX_CONNECTIONS'] ?? 50), minConnections: (int)($_ENV['DB_MIN_CONNECTIONS'] ?? 5) ); } /** * 获取单例实例 */ public static function getInstance(): self { if (self::$instance === null) { self::$instance = new self(); } return self::$instance; } /** * 执行查询操作 */ public function query(string $sql, array $params = []): array { $connection = $this->connectionPool->getConnection(); try { $stmt = $connection->prepare($sql); $stmt->execute($params); $result = $stmt->fetchAll(); return $result; } finally { $this->connectionPool->releaseConnection($connection); } } /** * 执行更新操作 */ public function execute(string $sql, array $params = []): int { $connection = $this->connectionPool->getConnection(); try { $stmt = $connection->prepare($sql); $stmt->execute($params); return $stmt->rowCount(); } finally { $this->connectionPool->releaseConnection($connection); } } /** * 执行事务操作 */ public function transaction(callable $callback) { $connection = $this->connectionPool->getConnection(); try { $connection->beginTransaction(); $result = $callback($connection); $connection->commit(); return $result; } catch (Exception $e) { $connection->rollBack(); throw $e; } finally { $this->connectionPool->releaseConnection($connection); } } /** * 获取连接池状态 */ public function getPoolStatus(): array { // 这里需要在AdvancedConnectionPool中添加获取状态的方法 return []; } } // 使用示例 class UserService { private DatabaseManager $dbManager; public function __construct() { $this->dbManager = DatabaseManager::getInstance(); } /** * 获取用户信息 */ public function getUserById(int $id): ?array { $users = $this->dbManager->query( "SELECT * FROM users WHERE id = ?", [$id] ); return $users[0] ?? null; } /** * 创建新用户 */ public function createUser(array $userData): int { $this->dbManager->execute( "INSERT INTO users (name, email, created_at) VALUES (?, ?, ?)", [ $userData['name'], $userData['email'], date('Y-m-d H:i:s') ] ); return $this->dbManager->query("SELECT LAST_INSERT_ID() as id")[0]['id']; } /** * 批量更新用户状态 */ public function batchUpdateUserStatus(array $userIds, string $status): int { return $this->dbManager->transaction(function($connection) use ($userIds, $status) { $placeholders = str_repeat('?,', count($userIds) - 1) . '?'; $sql = "UPDATE users SET status = ? WHERE id IN ($placeholders)"; $params = array_merge([$status], $userIds); $stmt = $connection->prepare($sql); $stmt->execute($params); return $stmt->rowCount(); }); } }最佳实践建议1. 配置优化// 环境变量配置示例 /* DB_HOST=localhost DB_PORT=3306 DB_NAME=myapp DB_USER=myuser DB_PASS=mypass DB_MAX_CONNECTIONS=100 DB_MIN_CONNECTIONS=10 DB_IDLE_TIMEOUT=300 */2. 监控和日志/** * 连接池监控工具 */ class ConnectionPoolMonitor { public static function logConnectionEvent( string $eventType, array $poolStats ): void { $logData = [ 'timestamp' => date('Y-m-d H:i:s'), 'event_type' => $eventType, 'pool_stats' => $poolStats ]; error_log(json_encode($logData)); // 发送到监控系统 if (function_exists('statsd_timing')) { statsd_gauge('db.connections.total', $poolStats['total_connections']); statsd_gauge('db.connections.available', $poolStats['available_connections']); } } }3. 性能调优参数// 数据库连接池推荐配置 $poolConfig = [ 'max_connections' => 50, // 最大连接数 'min_connections' => 5, // 最小连接数 'connection_timeout' => 30, // 连接超时时间 'idle_timeout' => 300, // 空闲连接超时时间 'wait_timeout' => 10 // 等待连接超时时间 ];总结数据库连接池优化的关键要点:连接复用:避免频繁创建和销毁连接资源控制:限制最大连接数防止资源耗尽健康检查:定期检查连接有效性自动清理:及时清理空闲和无效连接监控告警:实时监控连接池状态和性能指标通过实现高效的数据库连接池,可以显著提升PHP应用的数据库访问性能和系统稳定性。
2025年10月19日
0 阅读
0 评论
0 点赞