lsn是redo log的64位字节级偏移量,非普通计数器;它严格单调递增、仅用于比较与定位,不支持算术运算,每写入日志即按字节数累加,决定崩溃恢复起点和日志循环边界。

LSN 是什么,为什么它不是普通计数器
LSN 不是事务 ID 或时间戳,而是一个严格单调递增的 64 位整数,本质是 redo log 的字节级偏移量。每次写入 redo log,LSN 就增加对应日志记录的字节数。它不支持加减运算,只用于比较大小和定位——比如判断“某页是否已刷盘”或“某段日志是否已被覆盖”。
常见误解是把它当“日志条目序号”,但实际一条 DML 可能生成多段日志(如修改聚簇索引 + 二级索引),每段都推进 LSN;一个 INSERT 也可能因缓冲区 flush 触发多次小写入,LSN 连续但非等距增长。
如何从 show engine innodb status 看懂四个关键 LSN
执行 SHOW ENGINE INNODB STATUS\G 后,在 LOG 区域会看到四行 LSN 值,它们反映不同阶段的持久化进度:
-
Log sequence number:当前内存中log buffer的最新 LSN,即下一条日志将写入的位置 -
Log flushed up to:已成功fsync到磁盘ib_logfile*的最大 LSN -
Pages flushed up to:Buffer Pool 中最老脏页对应的 LSN,表示该 LSN 之前的数据页已落盘 -
Last checkpoint at:最近一次 checkpoint 记录在日志文件头部的 LSN,它是恢复起点
这四个值满足 Log sequence number ≥ Log flushed up to ≥ Pages flushed up to ≥ Last checkpoint at。若 Log flushed up to 长期滞后于前两者,说明磁盘 I/O 或 innodb_flush_log_at_trx_commit 配置可能成为瓶颈。
LSN 推进如何影响崩溃恢复与日志循环
LSN 推进直接决定两个关键行为:崩溃恢复范围和 redo log 文件复用边界。
MySQL 重启时,会从 Last checkpoint at 开始扫描 redo log,重放所有 LSN 大于该值的日志记录。这意味着 checkpoint 越新,需要重放的日志越少,启动越快。
而 redo log 是环形结构(ib_logfile0、ib_logfile1),LSN 推进到末尾后自动回绕。但不能覆盖“尚未 checkpoint 的日志”——InnoDB 用 checkpoint_lsn 和 write_lsn 控制安全水位。若 write_lsn - checkpoint_lsn 接近 innodb_log_file_size × 2,就会触发主动 checkpoint,避免日志空间耗尽阻塞写入。
哪些操作会意外拖慢 LSN 推进
LSN 推进本身很快,但它的“可见进度”常被其他机制掩盖:
- 设置
innodb_flush_log_at_trx_commit = 0:事务提交不强制刷 log,Log flushed up to可能长时间卡住,崩溃时最多丢失 1 秒日志 - 大事务未提交:其产生的大量 redo 日志持续占用 log buffer,且无法 checkpoint,导致
Log sequence number高速上涨但Last checkpoint at几乎不动 - 慢磁盘或高并发写入:即使
innodb_flush_log_at_trx_commit = 1,fsync延迟也会让Log flushed up to明显落后,引发写入抖动 - 未调优
innodb_log_buffer_size:小缓冲区导致频繁 flush,LSN 推进碎而密,增加系统调用开销
真正容易被忽略的是:LSN 推进不可逆,也不可跳过。哪怕手动删除 ib_logfile*,重启后 MySQL 会重建日志并重置 LSN 为 8704(起始值),但所有数据页头部的 FIL_PAGE_LSN 若仍大于新日志起始 LSN,实例将拒绝启动——这是 InnoDB 强一致性设计的硬约束。











