背景
mysql有慢日志的功能,可以记录下执行慢的sql,但是sql的慢日志有个问题就是一旦项目大了之后,给你一个sql,你也找不到是在哪里调用的,很难定位到哪里的操作慢,所以最好是代码里面能够记录一下,哪一行代码执行的sql慢,这样就减少了不少定位问题的时间。
代码实现
1,找到AppServiceProvider这个类,在boot中加入如下代码:
try {
DB::listen(function ($query) {
//如果是本地环境,记录下所有运行的sql,方便调试
if (app()->environment('local')) {
$tmp = str_replace('?', '"' . '%s' . '"', $query->sql);
$tmp = vsprintf($tmp, $query->bindings);
$tmp = str_replace("\\", "", $tmp);
Log::info($tmp);
}
if (app()->environment('production')) {
// 生产环境记录慢查询,超过一秒的执行时间记录下来
if ($query->time >= 1000) {
$tmp = mb_substr($query->sql, 0, 1000);
$tmp = str_replace('?', "'" . '%s' . "'", $tmp);
$tmp = vsprintf($tmp, $query->bindings);
$tmp = str_replace("\\", "", $tmp);
$sqlLength = mb_strlen($query->sql);
if ($sqlLength > 1000) {
$tmp .= '...' . (count($query->bindings)) . 'params';
}
$logData = [
'time' => $query->time,
'sql' => $tmp,
'trace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)
];
Log::error('slow sql log:'. json_encode($logData));
}
}
});
} catch (Exception $e) {
Log::error("slow sql exception", json_encode([$e->getCode(), $e->getMessage(), $e->getTraceAsString()]));
}
这样就能记录到哪行代码执行的sql慢,而且可以指定慢的时间