增量备份链断在一个数上:位点对不上时的排查与重建

一、链式备份靠三个数说话,少一个都不可信
链式备份的组织方式并不神秘:每个备份目录里会留下一个检查点文件,记录这一份的备份类型与起止位点;增量份要指向上一次成功备份的目录作为基线;工具在做增量之前会做一件事——把父份的结束位点和自己记录的起始位点拿出来比对,不相等就报错退出。这里的位点,本质上是数据库日志序列中的一个位置标记,各家的字段名不同,含义是一样的:它是一个数,不是一个文件时间。
由此得到父子判据的三条:类型、起止位点、基线指向。三者缺任一条,这份备份就不可信,即使它的作业状态写着成功。
这句话要展开成一个容易被忽略的区分:作业状态和链状态是两件事。作业状态描述”这次任务有没有跑完”,链状态描述”这份能不能被接进恢复路径”。监控只看前者,就会出现一片绿灯而实际不可恢复的库。我们在值守里坚持把它拆成两个字段,原因就在这里。
排查手段也直接来自这个结构:逐级读出各个目录里检查点记录的位点值,把它们抄成一张表做比对。位点对不上的那一格,就是断点。命令只是取数的手段,重点是抄出来的这张表要在断的时候还能查到。
二、没做完的那一份是怎么污染链条的
典型的成因不是备份工具算错了位点,而是”上一次没做完的那份被当成了新基线”。三条路径都会走到这个结果。
第一条,基线选取规则写成了”取目录里时间戳靠后的那一份”。作业失败时,目录可能已经创建、检查点文件可能已经写出但不完整,甚至写出了一个只包含起始位点的半份。下一次增量按”时间靠后”去取基线,就取到了一个不该被当父份的目录,校验必然不过。
第二条,清理策略按目录时间删除,以”份”为单位而不是以”链”为单位。删掉中间任何一份,它后面所有派生的增量都失去父份;剩下的一份虽然自身完好,但已经无法从基线走到它。这种断链在备份目录里完全看不出来,只有恢复时才暴露。
第三条,写入被打断或环境变了。磁盘余量不足导致检查点没写全;目录权限或属主变更导致后续作业能读不能写;备份窗口与大量写入或其它作业冲突,位点在两份之间跳了一段。第三种最难查,因为现象是间歇性的。
还有一条容易被归错的原因:目标实例做过调整(换版本、改参数、迁路径、动过插件),而链台账里没记录配置版本。这份库的旧链在新配置上的可用性是未验证的,不能假定能接着用。
三、排查四步,顺序不要换
发现校验不过或需要确认链是否连续时,按下面四步走,目标是把”断在哪一格”说清楚,而不是立刻重做全量。
- 逐级回读位点。从链上靠后的那份开始,按基线指向逐个回退,把每目录的类型、起始位点、结束位点、声称的父目录抄进一张表。抄到某一步发现父目录不存在或位点对不上,断点就在这一格。
- 核对基线指向的正确性。光看”父目录存在”不够,要确认被指向的那一份自身状态是成功且校验通过的,且它的链根与当前份一致。指向了一份失败的目录,是脚本按时间挑选的典型后果。
- 比对作业日志、磁盘与权限。确认失败发生在写出之前还是之后——之前意味着目录是空的或残留,之后意味着内容可用但状态字段没落。这两类处置完全不同,前者只能剔除,后者可以补齐状态后复用。
- 确认是否有并发写入或其它作业打断。核对同时间窗内的作业记录、日志切换、空间告警与权限变更。间歇性断链多半来自这一条,而不是配置错。
四步做完,应当能回答三个问题:断在哪一格、为什么断、断的那一段有没有可用替代。回答不了第三个问题就不要动手清理。
四、核心交付物:链台账、校验方法与失败处置
链台账是把上面所有事情固定下来的唯一办法。它不是备份目录列表,而是一张每份都有父指、并且能被查询的表。
| 字段 | 含义 | 校验方法 | 校验不过时的处置 |
|---|---|---|---|
| 备份标识与目录 | 这一份的唯一编号与存放路径 | 目录是否存在、内容是否非空 | 剔除出可用链并标记为不可选作基线 |
| 类型 | 全量、增量、日志备份三类之一 | 与链根的规则比对:增量必须有全量根 | 类型与父份规则冲突,直接判不可用 |
| 起始位点与结束位点 | 覆盖的日志区间两端 | 与父份结束位点做等值比对 | 不等即断链,记录断点区间,触发重建 |
| 父份指向 | 本份声明的基线目录 | 父份存在、状态成功、链根一致 | 改指向链上靠前且校验通过的那一份,或重做本份 |
| 链根与链序号 | 从哪一次全量派生、在链中第几环 | 从当前份回溯到根,环数是否连续 | 有空洞则本链只能用于恢复到空洞之前 |
| 作业状态 | 任务是否跑完 | 作业日志与退出码 | 单独一列,不参与可用性判定 |
| 链状态 | 校验通过与否 | 上面三项的综合判定结果 | 不可用时告警,按重建流程处理 |
| 目标实例与配置版本 | 属于哪个库、当时实例的配置版本 | 与恢复环境做一致性比对 | 不一致时该链只允许在同配置环境演练 |
| 大小与耗时 | 用于趋势与异常发现 | 与历史同类型偏离度 | 偏离过大先查完整性再决定是否可用 |
| 末次演练结论与时间戳 | 这条链最后一次被真实恢复验证的结果 | 由演练作业回写 | 超期未演练按不可用对待 |
| 负责人 | 出问题找谁 | 值守排班表核对 | 无人认领的链不进交付清单 |
校验的触发时机有三处:作业结束时做一次(自身完整性)、下一次增量开始前做一次(父子衔接)、演练时做一次(端到端可用性)。三次缺一不可,因为前两次只看数,只有第三次能证明这些数合起来真的能起来一个可用的库。
五、恢复侧的验证:作业成功但不可恢复的三种典型
恢复链路的顺序是先按链把各份合并应用,再做一致性与就绪处理,最后才是能否启动对外服务。校验通过只保证第一段能跑,不保证后两段没问题。三种”备份全都成功但库起不来”的情形各有原因。
第一种,缺中间份。表现为合并到某一步没有可应用的日志区间,只能恢复到空洞之前的时点。这类问题在清理策略改动之后出现,且往往在真正需要恢复时才发现,因此清理规则必须与链台账联动:删除前先确认没有后继份指向它。
第二种,只备了数据目录,没备事务日志。结果是位点无法衔接,数据文件与日志位置不匹配,即使文件都在也只能得到一个不一致的快照。判断方法很简单:检查点里的起止位点区间是否被日志备份覆盖。这一条要在台账里显式列一栏,不要靠人记。
第三种,目标实例配置与源不一致。路径、参数、排序规则、插件或字符集的差异,会让恢复过程报错或者起来之后行为不对。这一类不是备份问题,但一定会被先当成备份问题来处理,因此演练必须固定在与生产等价的环境上做,并且把配置版本记进台账。
按时间点恢复还多一层要求:日志备份的位点与数据份的位点要能衔接上目标时点。链连续但日志断档,同样做不到任意时点。这一项只能在演练里验,不能靠推理。
六、治理动作与交付时的备份矩阵
真正能把这件事从”运气”变成”能力”的动作只有几条,而且都发生在平时。
- 保留策略以链为单位。禁止删除链的中间环节;要清理只能整条旧链一起退,或者按”保留到第几个全量根”来表达。
- 每次全量之后强制做一次恢复演练并记录结论。演练不是加分项,它是把”作业成功”翻译成”能恢复”的唯一手段。
- 告警条件换成”末次成功恢复演练的时点是否超期”,而不是”末次备份是否成功”。前者的告警量会明显更大,因为它第一次开始说真话。
- 断链之后的处置要有预案而不是临场决定:立刻做一次全量作为新链根,同时把断链区间与影响范围(可恢复到的时点)记进台账并向业务方说明。
- 链台账由作业自己回写,人工补录只允许出现在事后修正,且必须留下修正原因。
交付给客户时,我们带的是一张备份矩阵,粒度到库:库名、备份方式与频率、保留策略、末次成功演练的时点、负责人、以及该库当前链能不能支持任意时点恢复。频率这一栏我们不给统一建议——同一个系统里不同库的变更量与恢复目标差别很大,只能由业务方按自己的恢复点目标填。
洹拓科技做值守交接时,把矩阵里三件事当验收线:能不能查出任意一个库当前的链是否连续;断链时有没有书面的重建与告知流程;末次演练的结论是谁签的。三条都有明确答案,这个库的备份才算交付过;只有作业调度截图的,都还在”看起来在备”的阶段。