2. SQL 回放基础:SQL执行日志的捕获原理、通用日志与慢查询日志的区别、开启与配置日志记录
SQL 回放的核心前提是获取真实的生产流量日志。本章将深入剖析 MySQL 执行日志的捕获原理,厘清通用日志与慢查询日志的本质区别,并手把手指导你完成日志的开启与配置。掌握这些基础,是后续进行精准回放与对比评审的基石。
2.1 SQL执行日志的捕获原理
MySQL 服务器在执行 SQL 语句时,会经过多个内部模块。日志捕获正是基于这些模块的钩子(Hook)机制,在特定阶段将 SQL 文本、执行时间、连接信息等关键数据写入文件或表。
核心捕获点:日志捕获发生在 SQL 语句解析与权限检查之后、执行器开始执行之前。这意味着日志中记录的 SQL 是经过语法校验的“合法”语句,但尚未经过存储引擎的实际数据读取或修改。
捕获流程可概括为以下步骤:
- 连接器接收请求:客户端发送 SQL 到 MySQL 服务器,连接器分配线程并验证用户身份。
- 查询缓存检查(可选):若开启查询缓存且命中,则直接返回结果,不记录日志。
- 解析器与预处理器:进行词法/语法解析,生成解析树,并检查权限。
- 日志写入点:在权限检查通过后、优化器生成执行计划前,日志模块根据配置决定是否将 SQL 写入日志缓冲区。
- 日志输出:日志缓冲区定期刷新到磁盘文件(或系统表),完成持久化。
实践要点:日志捕获点位于优化器之前,这意味着日志中记录的 SQL 不包含执行计划信息。若需要分析索引使用情况,必须结合
EXPLAIN 或慢查询日志中的额外字段。
2.2 通用日志与慢查询日志的区别
MySQL 提供两种主要的 SQL 日志类型:通用日志(General Log)和慢查询日志(Slow Query Log)。它们在记录范围、性能影响和使用场景上存在显著差异。
| 对比维度 | 通用日志(General Log) | 慢查询日志(Slow Query Log) |
|---|---|---|
| 记录范围 | 所有执行的 SQL 语句(包括查询、DML、DDL、连接/断开) | 仅记录执行时间超过 long_query_time 阈值的 SQL |
| 记录粒度 | 每条 SQL 一条记录,包含时间戳、用户、线程 ID、SQL 文本 | 每条慢 SQL 一条记录,包含时间戳、用户、执行时间、锁等待时间、返回行数、SQL 文本 |
| 性能影响 | 高:频繁的磁盘 I/O 和锁竞争,高并发下可能导致性能下降 10%-30% | 低:仅记录少量慢 SQL,对整体性能影响极小 |
| 存储方式 | 文件(默认)或 mysql.general_log 表 |
文件(默认)或 mysql.slow_log 表 |
| 主要用途 | 审计、安全分析、全量流量回放、调试 | 性能优化、慢查询定位、索引调优、回放压测 |
| 是否默认开启 | 否 | 否(但建议生产环境开启) |
性能警告:在生产环境开启通用日志需极其谨慎。高并发场景下,通用日志的磁盘写入会成为瓶颈,甚至导致数据库响应变慢。建议仅在低峰期或测试环境使用。慢查询日志则相对安全,是生产环境性能监控的标配。
2.3 开启与配置日志记录
日志的开启与配置主要通过 MySQL 系统变量实现。你可以通过 SET GLOBAL 动态修改(立即生效,但重启后失效),或写入配置文件 my.cnf(重启后生效)。
2.3.1 通用日志配置
通用日志的核心变量为 general_log 和 general_log_file。
-- 动态开启通用日志(立即生效)
SET GLOBAL general_log = ON;
-- 指定日志文件路径(可选,默认在数据目录下)
SET GLOBAL general_log_file = '/var/log/mysql/general.log';
-- 查看当前配置
SHOW VARIABLES LIKE 'general_log%';
配置文件方式(my.cnf):
[mysqld]
general_log = ON
general_log_file = /var/log/mysql/general.log
2.3.2 慢查询日志配置
慢查询日志的核心变量包括 slow_query_log、slow_query_log_file、long_query_time 和 log_queries_not_using_indexes。
-- 动态开启慢查询日志
SET GLOBAL slow_query_log = ON;
-- 设置慢查询阈值(单位:秒,支持小数)
SET GLOBAL long_query_time = 1.0;
-- 记录未使用索引的查询(强烈建议开启)
SET GLOBAL log_queries_not_using_indexes = ON;
-- 指定日志文件路径
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
-- 查看当前配置
SHOW VARIABLES LIKE 'slow_query_log%';
SHOW VARIABLES LIKE 'long_query_time';
配置文件方式(my.cnf):
[mysqld]
slow_query_log = ON
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1.0
log_queries_not_using_indexes = ON
回放配置建议:对于 SQL 回放场景,建议同时开启慢查询日志(用于性能基线)和通用日志(用于全量流量捕获)。但需注意:通用日志应在低峰期开启,并设置合理的日志轮转策略,避免磁盘空间耗尽。
2.3.3 日志输出格式与轮转
MySQL 支持将日志输出到文件或表。表模式便于 SQL 查询分析,但性能开销更大。推荐生产环境使用文件模式,并配合 logrotate 工具进行日志轮转。
| 输出方式 | 设置变量 | 优点 | 缺点 |
|---|---|---|---|
| 文件 | log_output = FILE |
性能好,磁盘 I/O 可控 | 分析需借助外部工具(如 mysqldumpslow) |
| 表 | log_output = TABLE |
可直接用 SQL 查询分析 | 性能开销大,表可能迅速膨胀 |
| 文件 + 表 | log_output = FILE,TABLE |
兼顾性能与查询便利性 | 双倍写入开销,不推荐生产使用 |
最佳实践总结:
- 性能基线/回放:开启慢查询日志(
long_query_time=0可记录所有 SQL,但慎用),配合log_queries_not_using_indexes。 - 全量流量回放:在低峰期开启通用日志,使用文件输出,并配置
logrotate每日轮转。 - 审计需求:通用日志 + 表输出,但需监控磁盘和性能。
- 避免:生产环境同时开启通用日志和慢查询日志的表输出模式。