高并发下PHP数据库连接池需依赖Proxy层(如ProxySQL)、连接池服务(如Swoole协程)或PDO持久连接(仅限简单场景);秒杀防超卖靠行锁原子扣减、Redis预减、队列削峰;慢查询优化重在精准定位与索引调整;读多写少一致性遵循先更库再删缓存+补偿机制。

高并发下数据库连接池怎么设计
PHP 本身不内置连接池,MySQLi 和 PDO 默认每次请求都新建连接(短连接),高并发时容易打满数据库连接数(如 MySQL 默认 max_connections=151)。真实项目中需靠外部组件或架构层解决:
- 用 Proxy 层:如 MySQL Router、ProxySQL 或 MaxScale,它们维护长连接池,复用后端连接,支持读写分离和自动故障转移
- 用 连接池服务:如使用 Swoole 启动常驻进程,通过协程 MySQL 客户端复用连接,配合连接数限制与超时回收(例如设置 max_idle_time 和 max_active)
- 应用层简单兜底:PDO 构造时启用
PDO::ATTR_PERSISTENT(持久连接),但要注意 PHP-FPM 模式下存在连接状态残留、事务未提交等风险,仅适合只读或简单场景,不推荐核心写操作
秒杀场景下如何避免超卖
超卖本质是多个请求同时读-改-写库存,造成数据不一致。关键不是“快”,而是“串行化关键路径”:
-
数据库行锁 + 原子扣减:用
UPDATE stock SET num = num - 1 WHERE id = ? AND num > 0,检查affected_rows === 1再确认下单,避免先查后更的竞态 -
Redis 预减库存:商品上架时把库存写入 Redis(如
SETEX item:1001:stock 3600 100),秒杀请求先DECR,为负则拒绝;成功后再异步落库,失败可回补(注意 Redis 单线程保证原子性) - 队列削峰:前端拦截后,请求进 Kafka/RabbitMQ,消费者单线程/分片处理,按序执行扣库存+创建订单,确保逻辑串行
大促期间慢查询激增怎么定位和优化
不能只看“执行慢”,要结合并发上下文分析:
- 开启 slow_query_log,设置
long_query_time=0.1(别用默认 1s),配合log_queries_not_using_indexes=ON抓出隐式全表扫描 - 用
SHOW PROCESSLIST或performance_schema查看高并发时哪些 SQL 处于Sending data或Locked状态,再结合EXPLAIN FORMAT=JSON看是否走了索引、是否用了临时表/文件排序 - 典型优化点:避免 SELECT *(减少网络和内存开销)、WHERE 条件字段加联合索引(如
ORDER BY created_at DESC LIMIT 20配合(status, created_at))、分页改用游标(WHERE id > ? ORDER BY id LIMIT 20替代OFFSET)
读多写少业务如何保障一致性
缓存与数据库双写不一致是高频陷阱,重点在“谁当主权威”和“失效时机”:
立即学习“PHP免费学习笔记(深入)”;
- 写操作必须 先更新数据库,再删缓存(Cache Aside),而不是更新缓存——否则并发写可能把旧值又刷进缓存
- 删缓存失败怎么办?加补偿机制:记录失败 key 到消息队列,由独立消费者重试;或用延迟双删(删一次 → 更新 DB → sleep 100ms → 再删一次),覆盖主从延迟窗口
- 对一致性要求极高的场景(如资金类),干脆绕过缓存,直接查库;或用 数据库 binlog + Canal 监听,变更时精准推送缓存更新,避免应用层双写逻辑



















