log_output参数介绍
log_output用于指定慢日志的存储方式,可以设置为TABLE、FILE或者NONE。
log_output='FILE' # 表示将日志存入文件slow.log,默认值是'FILE'
log_output='TABLE' # 表示将日志存入数据库,会写入mysql.slow_log表
log_output='FILE,TABLE' # 表示既写文件slow.log,又写mysql.slow_log表
log_output='NONE' # 表示禁用日志
示例:如下配置,mysql库下会生成一张slow_log表,用于记录数据库慢日志。
mysql> SHOW VARIABLES LIKE 'log_output';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_output | TABLE |
+---------------+-------+
#在线修改
mysql> SET GLOBAL log_output='TABLE';
#写入配置文件
[mysqld]
log_output=TABLE
设置log_output=TABLE存在的风险
- 慢日志文件较大时,读写slow_log会消耗资源,影响整库性能;
- xtrabackup物理备份成本较高,不仅占用空间大,而且恢复成本也高;
- 操作慢日志表可能引发死锁,导致数据库夯住,下面分享一个生产案例。
1> 问题描述
slow_log表生成的文件占用大量磁盘空间
在生产环境中,mysql数据盘使用率突然暴增,30分钟内增长200G,导致磁盘使用率达到100%,数据库挂起。分析发现在mysql库中产生了一个slow_log.CSN文件,且文件大小快速增长。

然后紧急清理slow_log表,但是执行truncate 失败,并且产生了大量MDL锁等待
执行truncate table slow_log命令卡主,一直等待mdl锁。


此时,数据库中的很多会话都卡主了,状态都处于Waiting for table metadata lock。

2> 引发MDL锁等待的原因
监控系统发起的请求一直在查询information_schema.tables表,它导致所有表处于open状态,导致truncate操作拿不到mdl锁。并且尝试查杀会话失败,线程卡在了killed状态。 (引发该问题的原因下面章节展开讲)

MDL锁分析
- 上图中的db_monitor用户查询information_schema.tables表时打开了所有表。导致truncate 操作申请不到mdl锁。
- truncate table slow_log语句导致大量业务执行DQL、DML执行完以后,很多符合慢日志条件的的语句无法写如慢日志表(slow_log),然后产生了大量的mdl锁等待。
3> 文件slow_log.CSN的由来
其实上面一连串故障的源头就是slow_log.CSN。网上鲜有它的介绍,最后在error.log时发现了一行相关报错。
2024-12-17T07:36:42.454236Z 3 [ERROR] Failed to write to mysql.slow_log: Incorrect key file for table 'slow_log'; try to repair it
查看资料,该文件确实是数据库产生的,结合日志信息,应该是slow_log中的一个错误行触发了repair,而slow_log.CSN文件就是修复slow_log时产生的临时文件。

它是一个文本文件,可以使用shell命令查看,里面记录的都是慢sql文本。

查询information_schema.tables卡主的原因
上文中监控系统发起的请求卡主,是因为查询information_schema.tables需要扫描所有表,但是slow_log表存在异常,正在自动修复中,所以查询线程卡主。
紧急恢复业务
为了尽快恢复业务,配置文件修改log_output=FILE,然后紧急重启数据库。
重启后成功truncate清空了slow_log表,然后.CSV文件释放了空间,但是.CSN文件并未释放,可能是强制重启导致,也可能是遗留的临时文件,最后手工删除后,数据库运行正常,无其他影响。

因此,慢日志写表风险不小,感觉不是特别友好,大家慎重使用吧。




