hyperf 框架中按日期分割 MySQL 慢查询日志
在使用 MySQL 数据库时,开启慢查询日志可以帮助我们识别和优化性能较差的查询语句。然而,随着时间的推移,慢查询日志文件会变得非常大,难以管理和分析。为了更好地组织和分析慢查询日志,我们可以将日志文件按日期进行分割。说明一下我的环境是 window for docker
配置 MySQL 慢查询日志
1. 使用 docker-compose.yml 配置慢日志
mysql:
container_name: mysql
environment:
- "TZ=Asia/Shanghai"
- MYSQL_ROOT_PASSWORD=12345678
- "explicit_defaults_for_timestamp=true"
- "lower_case_table_names=1"
image: mysql:8.0
restart: always
volumes:
#持久化
- mysql-data:/var/lib/mysql
# 将本地的初始化脚本目录挂载到容器中
- ./docker/mysql/backup.sql:/docker-entrypoint-initdb.d/backup.sql
# 挂载数据库日志目录 也可以就挂载到 runtime 目录下
- ./docker/mysql/logs:/var/lib/mysql/logs
ports:
- "3306:3306" # 确保端口映射允许宿主机上的应用连接到 MySQL
command: "--default-authentication-plugin=mysql_native_password --max_connections=200 --slow_query_log=1 --slow_query_log_file=/var/lib/mysql/logs/slow_query.log --long_query_time=1 --innodb-buffer-pool-size=1G"
# max_connections 最大连接数
# slow_query_log 开始慢查询日志
# slow_query_log_file 慢查询日志路径
# long_query_time 慢查询阈值"
2.1 使用 dockerFile 配置慢日志
mysql:
container_name: mysql
environment:
- "TZ=Asia/Shanghai"
- MYSQL_ROOT_PASSWORD=12345678
- "explicit_defaults_for_timestamp=true"
- "lower_case_table_names=1"
build:
context: ./docker/mysql
dockerfile: Dockerfile
restart: always
volumes: #持久化
- mysql-data:/var/lib/mysql
# 将本地的初始化脚本目录挂载到容器中
- ./docker/mysql/backup.sql:/docker-entrypoint-initdb.d/backup.sql
# 挂载数据库日志目录 也可以就挂载到 runtime 目录下
- ./docker/mysql/logs:/var/mysql/logs
# 挂载自定义配置文件目录
- ./docker/mysql/conf.d:/etc/mysql/conf.d
ports:
- "3306:3306" # 确保端口映射允许宿主机上的应用连接到 MySQL
command: "--default-authentication-plugin=mysql_native_password --max_connections=200 --innodb-buffer-pool-size=1G"
# max_connections 最大连接数
# innodb-buffer-pool-size 运行内存
2.2 配置 Dockerfile 文件
FROM mysql:8.0
# 这里修改为你自己的 slow-query-log.cnf 文件路径
COPY ./conf.d/slow-query-log.cnf /etc/mysql/conf.d/
# 修改文件权限 不然MySQL 报错:mysql: [Warning] World-writable config file '/etc/mysql/conf.d/slow-query-log.cnf' is ignored.
# 这个警告表示 MySQL 配置文件 /etc/mysql/conf.d/slow-query-log.cnf 的权限设置不正确,MySQL 出于安全考虑而忽略了该配置文件。
RUN chmod 644 /etc/mysql/conf.d/slow-query-log.cnf
export 3306
2.3 配置 slow-query-log.cnf 文件
[mysqld]
# 启用慢查询日志
slow_query_log = 1
# 慢查询日志文件的路径和名称
slow_query_log_file = /var/lib/mysql/logs/slow_query.log
# 慢查询的阈值,单位为秒
long_query_time = 1
#记录未使用索引的查询
log_queries_not_using_indexes = 1
# 限制未使用索引的查询的记录频率
log_throttle_queries_not_using_indexes = 5
# 记录慢速管理语句
log_slow_admin_statements = 1
# 记录慢速从库语句
log_slow_slave_statements = 1
# 日志输出方式,设置为 FILE 表示输出到文件
log_output = FILE
# 日志文件的保留天数,超过该天数的日志文件将被自动删除
expire_logs_days = 30
现在我们需要重启容器使配置生效
在宿主机上执行以下命令:
- docker-compose down
- docker-compose up -d
为了查看配置是否生效 我们进入到 MySQL 容器中
1. 进入容器的命令行:
docker exec -it mysql /bin/bash
连接到 MySQL:
mysql -u root -p
检查慢查询日志相关的变量:
SHOW VARIABLES LIKE 'slow_query%'; SHOW VARIABLES LIKE 'log_output';
- 确保
slow_query_log
的值为ON
,slow_query_log_file
的值为配置文件中指定的路径和名称,log_output
的值为FILE
。
手动触发一个慢查询:
- 在 MySQL 命令行中执行一个超过
long_query_time
设置的查询,例如:SELECT SLEEP(2);
- 检查
/var/lib/mysql/logs
目录下是否生成了按日期命名的慢查询日志文件。
3 创建定时任务
在 app/Crontab
目录下创建一个新的定时任务类 RotateSlowQueryLog
:
use Hyperf\Crontab\Annotation\Crontab;
use Hyperf\DbConnection\Db;
#[Crontab(name: "rotateSlowQueryLog", rule: "0 0 * * *", callback: "execute", memo: "每天凌晨 0 点执行按日期切割 MySQL 慢日志文件")]
class RotateSlowQueryLog
{
/**
* 按日期切割 MySQL 慢日志文件
* @return void
* @throws \Exception
*/
public function execute(): void
{
$path = BASE_PATH . '/docker/mysql/logs';
$logFile = "$path/slow_query.log";
$rotatedLogFile = "$path/slow_query_" . date('Ymd') . '.log';
if (!file_exists($path)){
throw new \Exception("No slow query log file found: $logFile");
}
//重命名日志文件
rename($logFile, $rotatedLogFile);
//切割日志文件时,我们需要确保 MySQL 能够继续写入新的日志文件。为了解决这个问题,我们可以在重命名日志文件后,通知 MySQL 重新打开日志文件。
Db::statement("SET GLOBAL slow_query_log = 'OFF'");
Db::statement("SET GLOBAL slow_query_log = 'ON'");
}
}
配置完成
本作品采用《CC 协议》,转载必须注明作者和本文链接