2. SQL 回放基础:SQL执行日志的捕获原理、通用日志与慢查询日志的区别、开启与配置日志记录

SQL 回放的核心前提是获取真实的生产流量日志。本章将深入剖析 MySQL 执行日志的捕获原理,厘清通用日志与慢查询日志的本质区别,并手把手指导你完成日志的开启与配置。掌握这些基础,是后续进行精准回放与对比评审的基石。

2.1 SQL执行日志的捕获原理

MySQL 服务器在执行 SQL 语句时,会经过多个内部模块。日志捕获正是基于这些模块的钩子(Hook)机制,在特定阶段将 SQL 文本、执行时间、连接信息等关键数据写入文件或表。

核心捕获点:日志捕获发生在 SQL 语句解析与权限检查之后、执行器开始执行之前。这意味着日志中记录的 SQL 是经过语法校验的“合法”语句,但尚未经过存储引擎的实际数据读取或修改。

捕获流程可概括为以下步骤:

  1. 连接器接收请求:客户端发送 SQL 到 MySQL 服务器,连接器分配线程并验证用户身份。
  2. 查询缓存检查(可选):若开启查询缓存且命中,则直接返回结果,不记录日志。
  3. 解析器与预处理器:进行词法/语法解析,生成解析树,并检查权限。
  4. 日志写入点:在权限检查通过后、优化器生成执行计划前,日志模块根据配置决定是否将 SQL 写入日志缓冲区。
  5. 日志输出:日志缓冲区定期刷新到磁盘文件(或系统表),完成持久化。
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 每日轮转。
  • 审计需求:通用日志 + 表输出,但需监控磁盘和性能。
  • 避免:生产环境同时开启通用日志和慢查询日志的表输出模式。