undo log是mysql InnoDB存储引擎中重要的日志类型,主要作用是记录事务修改前的数据版本,用于事务回滚和MVCC多版本查询。当undo log出现异常时,可能会导致事务无法正常回滚、长事务阻塞、数据库性能下降等问题,需要按照规范的流程逐步排查。

undo log常见问题表现
在排查之前,首先需要明确undo log异常的常见表现,方便快速定位问题方向:
- 事务执行回滚操作时提示失败,或者回滚后数据没有恢复到修改前的状态
- 数据库中大量长事务长时间运行,导致undo log文件持续增长,占用大量磁盘空间
- 执行查询时出现数据版本错乱,读取到不符合预期的历史数据
- mysql错误日志中出现undo log相关的报错信息,比如undo log损坏、空间不足等
基础排查步骤
1. 查看undo log相关参数配置
首先需要确认mysql的undo log相关参数是否符合预期,避免因参数配置不当引发问题。可以通过如下sql查看核心参数:
-- 查看undo log相关参数 SHOW VARIABLES LIKE 'innodb_undo%';
需要重点关注的参数包括:
innodb_undo_directory:undo log文件的存储目录,确认目录是否存在且有写入权限innodb_undo_tablespaces:undo log表空间数量,默认值为2,若为0则undo log存在系统表空间中innodb_undo_logs:单个事务允许使用的最大undo log数量,默认值为128innodb_undo_log_truncate:是否开启undo log自动截断,默认关闭,开启后可以避免undo log文件无限增长
2. 查看当前undo log的使用情况
可以通过InnoDB的状态信息查看undo log的实时使用情况,执行如下命令:
-- 查看InnoDB引擎状态,包含undo log相关信息 SHOW ENGINE INNODB STATUSG
在输出的结果中,找到TRANSACTIONS部分,可以看到当前活跃事务的undo log使用情况,以及是否存在长事务占用大量undo log。如果看到某个事务的undo log entries数值很大,且事务状态为RUNNING很久没有变化,就需要重点排查该事务。
3. 检查undo log文件状态
如果参数和运行时状态没有异常,需要进一步检查undo log文件本身的状态。首先到innodb_undo_directory配置的目录下,查看undo log文件是否存在、大小是否正常。undo log文件默认命名为undo_001、undo_002等,如果文件大小异常增长,或者出现文件损坏(比如大小为0、无法读取),就需要进一步处理。
常见场景排查与解决
场景1:undo log文件持续增长,磁盘空间不足
这种问题通常是因为存在长事务没有提交,导致undo log无法被回收。排查步骤如下:
- 先通过
SHOW PROCESSLIST查看当前所有运行的事务,找到执行时间很长且未提交的事务 - 确认该事务是否可以终止,如果可以则执行
KILL 事务对应的线程ID终止事务,事务回滚后会自动释放对应的undo log - 如果长事务无法终止,可以开启
innodb_undo_log_truncate参数,让mysql自动截断过大的undo log文件,开启方式如下:
-- 动态开启undo log自动截断,重启后失效,如需永久生效需要写入配置文件 SET GLOBAL innodb_undo_log_truncate=ON; -- 设置undo log截断检查间隔,默认值为128,单位为秒 SET GLOBAL innodb_undo_log_truncate_interval=128;
场景2:事务回滚失败,提示undo log相关错误
这种问题通常是undo log文件损坏或者丢失导致的。排查步骤如下:
- 先查看mysql的错误日志,确认具体的报错信息,比如是否是undo log文件无法读取、校验失败等
- 如果是单个undo log文件损坏,且数据库有备份,可以先停止mysql服务,删除损坏的undo log文件,从备份中恢复对应的文件,再启动服务
- 如果没有备份且损坏不严重,可以尝试使用mysql的修复工具尝试修复,但是修复前一定要先备份所有数据,避免数据丢失
- 如果损坏严重无法修复,只能通过全量备份恢复数据库,恢复后需要检查事务相关的业务代码,避免再次出现类似问题
场景3:MVCC查询出现数据不一致
这种问题通常是undo log版本链出现异常,可能是事务没有正确提交或者回滚,导致历史版本数据错乱。排查步骤如下:
- 先确认查询的表是否开启了事务支持,MyISAM引擎不支持事务和MVCC,不会出现undo log相关的问题
- 查看当前是否有未提交的事务修改了查询涉及的数据,未提交的事务修改的数据不会对外可见,但是如果事务异常中断可能导致undo log残留
- 可以尝试重启mysql服务,让InnoDB引擎重新初始化undo log相关的结构,重启后如果问题仍然存在,需要检查业务代码中事务的使用逻辑,是否存在事务没有正确提交或者回滚的情况
日常维护建议
为了避免undo log相关问题的出现,日常运维中可以采取以下措施:
- 尽量避免长事务,业务代码中事务执行时间尽量控制在秒级,执行完成后及时提交或者回滚
- 开启undo log自动截断功能,避免undo log文件无限增长占用磁盘空间
- 定期监控undo log的使用情况,设置磁盘空间告警,当undo log目录磁盘使用率过高时及时处理
- 定期备份数据库,出现undo log损坏时可以快速恢复,减少数据丢失风险