thinkphp如何做sql执行时间监控_thinkphp慢查询阈值告警详解【详解】

ThinkPHP 本身不拦截或记录慢 SQL,真正的慢查询监控必须依赖 MySQL 服务端配置;框架层只能做辅助计时和日志打点,不能替代数据库原生 slow_query_log。

MySQL 服务端必须开启 slow_query_log

这是所有后续监控的前提。PHP 层加再多 microtime(true) 都无法捕获连接池复用、预处理语句、主从延迟等真实耗时场景。

执行 SHOW VARIABLES LIKE ‘slow_query_log%’; 确认当前状态;若 slow_query_log 为 OFF,需手动开启动态开启(重启失效):SET GLOBAL slow_query_log = ON;永久生效:在 /etc/mysql/my.cnf 的 [mysqld] 段添加三行:slow_query_log = ONslow_query_log_file = /var/log/mysql/mysql-slow.loglong_query_time = 1.0/var/log/mysql/ 目录必须由 mysql 用户可写,否则日志静默失败——查不到日志时先检查这个long_query_time 支持小数(如 0.5),单位是秒,不是毫秒

ThinkPHP 3.2 中手动埋点 SQL 执行时间

适用于无法修改 MySQL 配置的老旧环境,或需要快速定位某段模型代码的耗时瓶颈。但注意:它只测 PHP 层发起查询到返回结果的时间,不含网络往返、锁等待、磁盘 IO 等真实数据库耗时。

在 Db::execute() 或 Model::select() 前后插入计时逻辑,例如:$sql_start = microtime(true);$result = Db::table(‘user’)->where(‘id’, 1)->find();$sql_end = microtime(true);$s_e_time = round($sql_end – $sql_start, 3);if ($s_e_time >= 1) { $log = "执行耗时{$s_e_time}秒, SQL: " . Db::getLastSql() . "\r\n" . ‘请求地址:’ . $_SERVER[‘REQUEST_URI’]; write_log_sql($log, ‘selectSQL’);}write_log_sql() 是自定义函数,需确保写入路径可写、有按日轮转机制不要在循环内高频调用 microtime(true),微秒级精度在高并发下有开销该方式无法覆盖事务块内多条语句、query() 原生执行、以及底层 PDO 直接调用的场景

ThinkPHP 5+ 使用 Db::listen() 捕获每条 SQL 耗时

比手动埋点更统一,且能拿到执行时间和执行计划(EXPLAIN),但仅限于框架封装的查询路径。

立即学习“PHP免费学习笔记(深入)”;

在应用初始化位置(如 common.php 或中间件)注册监听:Db::listen(function ($sql, $time, $explain) { if ($time >= 0.5) { // 单位:秒 Log::record("[SLOW] {$sql} [Time:{$time}s]", ‘sql’); }});$time 是浮点数,单位秒,精度取决于底层 PDO::getAttribute(PDO::ATTR_DRIVER_NAME) 实现开启后默认不再写 SQL 日志,需自行调用 Log::record() 或写文件$explain 仅在配置了 ‘sql_explain’ => true 且语句可被 EXPLAIN 时才有值不捕获 Db::raw()、存储过程调用、或直接使用 PDO::query() 的语句

TP5/6/8 的 slow_query_time 配置是伪阈值

这个配置项只影响框架是否在调试日志中“标记”某条 SQL 为慢查询,**不会触发任何告警、不写独立日志、不中断执行、也不上报指标**。它本质是日志着色开关,不是监控开关。

配置示例(config/database.php):’slow_query_time’ => 500,单位是毫秒只有当 ‘debug’ => true 时,该值才生效;生产环境 debug=false 下完全无效即使生效,也只在页面底部调试栏或 runtime/log 的 debug 日志里出现 [SLOW QUERY] 前缀,无结构化输出误以为设了这个就能告警,是线上慢查询漏报最常见的原因

真正可靠的慢查询告警,必须组合 MySQL slow log + 文件增量扫描(如 tail -F + awk) + Prometheus Exporter 或自定义脚本上报。框架层的计时只能帮你缩小问题范围,不能代替数据库服务端的日志源头。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。