不能用 sleep() 模拟数据库延迟,因为它会阻塞 php-fpm 进程、降低并发能力;应使用 mysql 的 sleep() 函数或 proxysql 注入网络层延迟,以真实触发超时、日志和告警机制,并验证代码对慢依赖的容错能力。

不能用 sleep() 在 Web 请求里“模拟数据库延迟”——它会卡住整个 PHP-FPM 进程,不是测数据库,是在测你自己的阻塞能力。
为什么直接 sleep() 不行
你在控制器里写 sleep(2),看起来像“数据库慢了 2 秒”,实际效果是:PHP 进程挂起、FPM worker 被占满、并发能力归零、Nginx 可能先超时断连。这不是模拟 DB 延迟,是制造服务雪崩。
真正要测的,是「查询执行耗时」本身,而不是让整个请求线程停摆。
- DB 延迟发生在连接建立后、SQL 执行中,
sleep()发生在 PHP 层,完全不在同一链路 - MySQL 的
innodb_thread_concurrency、锁等待、慢查询日志、执行计划这些真实指标,sleep()一概不触发 - 某些 ORM(如 ThinkPHP)会在
select()时才真正建连+发包,你提前sleep()根本没覆盖到关键路径
用 MySQL 自带的 SLEEP() 函数注入延迟
在 SQL 层面让查询变慢,才贴近真实场景。例如:
SELECT *, SLEEP(1.5) FROM user WHERE id = 123;
这条语句会让 MySQL 线程挂起 1.5 秒后再返回结果,PHP 层感知到的就是一次“真慢查询”,能触发 PDO 的超时、框架的查询日志、甚至慢查询告警。
- 只在开发/测试环境用,上线前必须删掉
SLEEP()函数调用 - 避免在
INSERT/UPDATE中用,可能阻塞写锁或事务提交 -
SLEEP()参数单位是秒,支持小数(如0.3),但最小精度受 MySQL 版本限制(5.7+ 支持 sub-second) - 配合
SHOW PROCESSLIST可观察到该连接状态为Sleep,验证是否生效
更可控的本地模拟:用 ProxySQL 或 Docker 注入延迟
如果需要稳定、可配置、不影响其他开发任务的延迟环境,推荐用 ProxySQL 做中间层代理,在转发 SQL 前加 delay:
- Docker 启动 ProxySQL + MySQL 组合,通过
mysql -h 127.0.0.1 -P 6033连代理而非直连 DB - 在 ProxySQL 配置中对匹配
SELECT.*FROM user的规则添加delay = 800(单位毫秒) - 这样所有符合条件的查询都会被统一拖慢,且 PHP 代码完全无感,也不用改任何 SQL
- 比改代码或改 MySQL 配置更安全,重启容器即恢复,适合 CI 测试或本地压测
注意 ProxySQL 的 delay 是网络层延迟,不等同于 MySQL 内部执行耗时,但它能有效暴露客户端重试、连接池复用、超时设置等问题——这才是你真正该关心的。
最容易被忽略的一点
本地模拟延迟,目标从来不是“让响应变慢”,而是验证你的代码能否正确应对慢依赖:是否设置了 PDO::ATTR_TIMEOUT?是否用了 curl_multi_init() 并行查多个服务?是否在 catch 里做了降级或重试?
如果你的代码连 mysqli_connect() 都没设超时,那无论怎么模拟 DB 延迟,都只是在等它自己崩溃。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











