mysql如何分析事务日志_mysql redo log与undo log协作

5次阅读

mysqlredo log 写入是否正常需通过 show engine innodb status 查看 log sequence number 与 log flushed up to 的差值,并监控 innodb_os_log_written 和 innodb_os_log_fsyncs 增量;undo log 清理依赖最老活跃读视图,长事务会阻塞 purge;崩溃恢复先重放 redo log(前滚),再用 undo log 回滚未提交事务;二者协同由 innodb 自动调度,关键风险在于未结束的长事务。

mysql如何分析事务日志_mysql redo log与undo log协作

怎么看 MySQL 的 redo log 写入是否正常

redo log 不是靠“查日志文件”来分析的,它默认不落盘为可读文本,而是由 InnoDB 管理的循环写入二进制文件(ib_logfile0ib_logfile1)。想确认它是否在工作,得看运行时状态和写入压力反馈。

  • SHOW ENGINE INNODB STATUSGLOG 小节,重点关注 Log sequence number(当前 LSN)和 Log flushed up to(刷到磁盘的 LSN),两者差距大说明刷盘滞后
  • 监控 Innodb_os_log_written(累计写入字节数)每秒增量,配合 Innodb_os_log_fsyncs(fsync 次数)看是否频繁刷盘——若写入量大但 fsync 很少,可能是 innodb_flush_log_at_trx_commit=2 在起作用
  • 别直接用 hexdumpstringsib_logfile*,内容是结构化 binary,强行解析会误判;真要取证,用 mysqlbinlog --base64-output=DECODE-ROWS 配合 binlog 更靠谱

undo log 什么时候会被清理,为什么事务一提交就查不到旧版本了

undo log 不是随事务提交立刻删除的,它的生命周期取决于「最老的活跃读视图」(即未提交的事务或未释放的 consistent read snapshot)。InnoDB 用 purge Thread 异步回收,但前提是没被任何事务需要。

  • 长事务是 undo log 积压的头号原因:执行一个跑了 10 分钟的 select(哪怕只是 SELECT SLEEP(600)),所有在此期间产生的 undo 都不能清理
  • information_schema.INNODB_TRX 里看 TRX_STARTEDTRX_ROWS_MODIFIED,能快速定位“钉子户”事务
  • innodb_max_purge_lag 是个软限制,它不会阻止新写入,只通过延迟 INSERT/UPDATE/delete 来减缓 purge 压力,别指望它解决根本问题

redo log 和 undo log 怎么协同保证崩溃恢复

崩溃恢复时,MySQL 启动阶段先重放 redo log(前滚,Redo Phase),把所有已提交但没写入数据页的变更补上;再根据 redo 中的事务状态,对未提交事务做 undo log 回滚(回滚,Undo Phase)。两者缺一不可,顺序也不能颠倒。

  • 如果 innodb_log_file_size 太小(比如默认 48MB),高并发写入容易触发频繁 checkpoint,导致 redo 循环覆盖过快,万一 crash 时最新 redo 还没刷盘,就会丢数据
  • undo log 存在 system tablespace(5.7)或独立表空间(8.0+ innodb_undo_tablespaces),但它不参与 crash recovery 的“重放”,只用于 rollback 和 MVCC——所以删错 undo 表空间会导致无法回滚、查询报错 Error 1558 (HY000): column count of mysql.user is wrong 这类元数据异常
  • 不要关 innodb_undo_log_truncate:它控制 undo 表空间自动截断,关了会导致 undo 占满磁盘且无法收缩

SELECT ... FOR UPDATE 时 undo log 和 redo log 谁先写

语句执行过程中,先生成 undo log 记录旧值(用于可能的回滚和 MVCC),再修改数据页并记 redo log(确保物理变更可重放)。这个顺序是硬编码在 InnoDB 事务流程里的,没法调换。

  • 即使事务最终 COMMIT,undo log 也不会立即消失——只要还有其他事务需要读取该行的历史版本(比如开了 REPEATABLE READ 并早于本事务启动),它就得留着
  • redo log 写入时机受 innodb_flush_log_at_trx_commit 控制:1 是每次 commit 都 fsync(安全但慢),02 可能丢最近 1 秒事务,别在线上库瞎设
  • performance_schema.data_locks 能看到当前哪些行被 FOR UPDATE 锁住,但看不到 undo 是否已分配——那部分在内存中,只有崩溃后从磁盘 recover 时才真正用到

事情说清了就结束。redo 和 undo 的协作不在代码里显式调用,而在事务生命周期每个关键节点被 InnoDB 自动调度;真正容易出问题的,从来不是“怎么配”,而是“有没有人忘了关掉那个跑了一天的测试事务”。

text=ZqhQzanResources