thinkphp 不归档数据库慢日志,mysql 慢日志需用 logrotate 配合 flush-logs 归档;tp 慢查询日志由框架记录在 runtime/log/,与 mysql 慢日志来源、格式、用途均不同。

ThinkPHP 本身不直接归档数据库慢日志,它只负责记录应用层的慢查询(如 SQL 执行超时),而真正的 MySQL 慢查询日志由数据库自身生成、存储和管理。归档动作必须由外部脚本或系统任务完成。
TP5/6 的 slow_query_time 是应用层拦截,不是 MySQL 慢日志
TP 配置中的 slow_query_time(单位毫秒)仅控制框架是否在日志中写入“该 SQL 执行耗时超标”的警告,例如:
2026-04-11 12:05:23 [ warning ] Slow query: SELECT * FROM users WHERE status = 1 (time: 842ms)
这类日志写入的是 TP 的运行时日志(如 runtime/log/xxxx.log),和 MySQL 的 slow_query_log_file 完全无关。两者容易混淆,但来源、格式、用途都不同。
- TP 慢查询日志:可读性强,带 PHP 调用栈(若开启
debug),适合快速定位业务代码问题 - MySQL 慢日志:原始、带锁时间、扫描行数、客户端 IP 等,是性能分析的黄金数据源
- TP 日志默认不自动切割;MySQL 慢日志需手动配置
log_output=FILE+slow_query_log才能落地为文件
MySQL 慢日志文件怎么归档?用 logrotate 最稳
不要自己写 PHP 脚本去 rename 或 gzip MySQL 慢日志——MySQL 进程会持续写入,直接操作易导致日志丢失或损坏。正确做法是交给 logrotate,并配合 mysqladmin flush-logs。
示例 /etc/logrotate.d/mysql-slow:
/var/log/mysql/mysql-slow.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 640 mysql mysql
sharedscripts
postrotate
if [ -f /var/run/mysqld/mysqld.pid ]; then
mysqladmin --defaults-file=/etc/mysql/debian.cnf flush-logs 2>/dev/null || true
fi
endscript
}
-
flush-logs会关闭当前 slow log 文件并新建一个,确保归档的是“已写完”的完整文件 -
compress自动用 gzip 压缩,归档后变成mysql-slow.log.1.gz - 比手写 PHP 归档脚本更可靠,避免竞态条件和权限问题
TP 应用日志(含慢查询警告)如何切割?靠 think\log\driver\File 配置
TP5.1+ 和 TP6 默认使用 File 日志驱动,支持按日/大小自动分割,无需额外命令行工具。关键配置项在 config/log.php 中:
-
'time_format' => 'c':确保日志名含标准时间戳 -
'file_size' => 2097152(2MB):单文件上限,超限即切新文件 -
'apart_level' => ['error', 'sql']:把 SQL 慢查询单独写入sql子目录,方便过滤 -
'max_files' => 30:保留最多 30 个日志文件,旧的自动删除(TP6.3+ 支持)
注意:slow_query_time 触发的日志,只有当 SQL 实际执行完毕且超时,才会被记录到 sql 日志里——如果查询卡死在连接阶段或被 kill,TP 层根本捕获不到。
想合并分析 TP 日志 + MySQL 慢日志?加 /* APP=xxx */ 注释最实用
在 TP 的 DB 查询前注入统一注释,让两条日志能对齐:
Db::name('users')->where('status', 1)->comment('APP=user_list')->select();
这样 MySQL 慢日志里会出现:
# User@Host: php_app[php_app] @ 10.0.1.5 [10.0.1.5] # Query_time: 1.234567 Lock_time: 0.000123 Rows_sent: 100 Rows_examined: 10000 SET timestamp=1744344323; /* APP=user_list */ SELECT * FROM users WHERE status = 1;
再配合 TP 日志里的 [ sql ] SELECT * FROM users WHERE status = 1 行,就能 1:1 关联请求上下文。没有这个标记,跨系统查问题等于盲人摸象。
真正难的不是切割或压缩,而是让日志之间有可追溯的锚点;没锚点的归档,只是把一堆碎片换个地方存着。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











