3.3 事务日志与恢复机制:先记账,再干活


3.3 事务日志与恢复机制:先记账,再干活

本节摘要:事务日志是存储引擎的心电图——每一笔改动先顺序记入日志(WAL),崩溃后靠重放日志找回未落盘的数据。本节讲清 LSN、恢复模式、VLF 与三阶段崩溃恢复,并处理两个高频运维事故:日志文件疯长与 VLF 碎片。这一节是第 6 章备份还原与 Always On 的理论地基。

数据库的心电图在日志里

第 2 章埋了个伏笔:脏页刷盘前,对应的日志必须先落盘,这条预写日志规则(WAL)是整套恢复体系的地基。它的含义值得掰开:数据页是随机写的,崩溃瞬间缓冲池里没刷的脏页全丢;日志是顺序追加的,每一笔改动都先于数据落盘。于是崩溃后只要日志还在,就能把丢掉的改动重放出来。 durability(持久性)不是靠"数据及时写盘"实现的,而是靠"日志必然先写"实现的——这个视角转换是理解本章所有机制的钥匙。

日志的每次记录有一个逻辑坐标:日志序列号(LSN),全局递增。整个恢复体系就是围绕 LSN 建立的线性历史:检查点推进了恢复起点,备份记录了自己的 LSN 区间,还原时按 LSN 顺序拼接日志链。你在第 6 章会看到"日志链断裂"这种表述,指的就是 LSN 序列缺了一环。

恢复模式:选择你想要的记账颗粒度

三种恢复模式决定日志的记账策略。简单恢复:检查点后日志自动截断重用,账本只保留最近的流水,只能还原到最近的备份点,适合可容忍数据丢失的非关键库(测试、日志型数据)。完整恢复:日志一直保留到下次日志备份,可以从全备加日志链还原到任意时点,生产库默认之选。大容量日志恢复:完整模式的变体,批量操作最小化记日志,换性能但破坏时点还原能力,只建议在大批量导入的窗口临时切换、事后立刻切回并补一次日志备份。

维度 简单恢复 完整恢复
日志截断 检查点自动截断 需日志备份触发
还原能力 到最近备份点 任意时点
日志体积 小且自持 与备份频率正相关
适用场景 测试、可重建数据 生产业务库
SELECT name, recovery_model_desc AS 恢复模式, log_reuse_wait_desc AS 日志重用等待原因 FROM sys.databases; -- 日志疯长时第二列是破案线索:LOG_BACKUP 说明在等日志备份, -- ACTIVE_TRANSACTION 说明有事务一直没提交,是应用连接泄漏的典型指纹。

两次高频事故的卷宗

第一桩:日志文件涨到 300GB 把磁盘塞满。按上面查询取证,日志重用等待显示 LOG_BACKUP——这个库设的完整恢复模式,但从没做过日志备份,日志自然无限累积。处置顺序是业务优先:先补做一次日志备份让日志立刻可截断,再建立每十五分钟一次的日志备份作业,最后把日志文件收缩回合理体积(收缩只在事后做一次,绝不做日常例行动作)。另一种答案也常见:如果业务其实只需要简单恢复的能力,直接切换恢复模式,账本自持。关键认知:日志疯长不是日志的错,是恢复模式与备份策略不匹配的错。

第二桩:日志文件 500GB 里躺了上万个 VLF。日志文件内部被划成一段段虚拟日志文件(VLF),频繁的自动小步增长会产生海量微小 VLF;崩溃恢复、日志备份、可用性组的每个操作都要扫描 VLF 清单,实例重启时间从一分钟拖到一小时。处置:收窄日志后以较大步长一次性重建(增长到目标大小再收缩一次),让 VLF 数量回到几十到几百的健康区间;治本是固定日志增长步长、提前扩容。两桩事故指向同一条纪律:日志文件的增长策略要在上线前定好,而不是让业务高峰替你实验

崩溃恢复的三阶段舞蹈

实例重启或故障切换后,每个数据库自动走三阶段恢复。分析阶段:从最后一个检查点扫描日志末尾,确定崩溃时哪些事务未提交;重做阶段:把所有已提交但可能未落盘的改动按 LSN 顺序重放——不管那页脏没刷盘,重放保证向前滚;撤销阶段:把未提交事务的改动反向回滚,被撤销的事务对用户表现为"从未发生",这正是原子性的兑现。从 2019 版起配合加速数据库恢复(ADR),撤销阶段被重构为秒级,长事务回滚不再阻塞——这对经常手滑写大 UPDATE 的运维是个福音。

理解三阶段后,"为什么还原到时点要先还原全备再按序还原日志"就不神秘了:全备给底片,日志链按 LSN 顺序重放到目标时刻——第 6 章的还原演练会把这个流程跑成肌肉记忆。

加速恢复:把撤销从小时级压到秒级

传统恢复的痛点集中在撤销阶段:一个跑了两小时的事务被回滚,通常要再花差不多的时间——崩溃恢复、手动 KILL、大事务改错,全都受制于此。加速数据库恢复(ADR)重构了这套机制:所有版本改写进库内的持久版本存储(PVS),撤销不再依赖正向重放后逆序回滚,而是直接用版本还原,秒级完成;正在运行的事务被中止不再阻塞后续恢复,长事务回滚从"全库等它"变成"无人等它"。代价是每行多一份版本指针、PVS 占用存储,并有后台清理任务持续回收旧版本——启用后要把 PVS 的空间监控纳入巡检,异常膨胀通常意味着某个老事务长期持有快照。
ADR 与快照隔离的关系也值得澄清:它不改变隔离级别语义,改的是引擎实现撤销的方式;两者可以叠加,高并发加长事务并存的库(秒杀库存、大批量修数)收益最明显。启用是一条数据库级语句加一次短暂切换,建议先在从库或测试环境验证 PVS 增长曲线,再推广到主库。

本节要点回顾

  • WAL 是地基:日志先于数据落盘,持久性靠"必然先记账"而非"数据及时写盘";
  • LSN 是历史坐标:检查点、备份、还原全靠 LSN 排序,日志链一断时点还原即失效;
  • 恢复模式对齐业务:关键库完整恢复加规律日志备份,非关键库简单恢复自持;
  • 日志疯长两病因:等日志备份(策略缺失)或有事务不提交(连接泄漏),用日志重用等待原因一查便知;
  • VLF 是隐形成本:小步自动增长制造海量 VLF,拖慢恢复与备份,固定大步长是治本;
  • 三阶段恢复:分析定未决、重放保已交、撤销清未交,ADR 把撤销提速到秒级。

存储引擎到此走完:页怎么放、数据怎么组织、改动怎么记账。下一章轮到主角登场——一条 SQL 进了引擎之后,优化器如何替它选路,执行计划又该怎么读懂。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U