第 8 / 23 篇

第7章:把二进制日志变成源库失联后仍可使用的归档

在源容器里运行mysqlbinlog,看到熟悉的订单变更,很容易产生已经完成时间点恢复的感觉。但如果源容器停止、数据卷损坏或者服务器无法登录,这条命令还成立吗?真正的归档恢复必须让日志离开原写入位置,并且能够在源服务不可用时由独立工具读取。

从活动文件到封口文件

活动binlog持续追加。直接复制时需要理解文件尾部是否完整、读到哪里、校验和怎样验证。教学实验选择先执行FLUSH BINARY LOGS,让目标文件关闭,再复制已经封口的文件。这样归档内容不再被后续写入改变,文件长度与摘要具有稳定意义。

程序从备份坐标提取文件名,保存恢复所需的开始位置;完成两笔合法事务和误删后,轮转日志,再用docker cp复制这份真实文件到任务自己的临时归档目录。报告记录归档文件名、字节数、SHA-256、封口方式和工具挂载条件。原始文件不需要伪装成手写SQL,MySQL的真实事件结构得到保留。

复制完成后源容器执行docker stop停止(十秒宽限后可能强杀,实际退出码写入报告)。回放工具是另一个无网络容器,只读挂载归档目录。它既没有源库网络,也没有源库数据卷,只能读取归档中的文件。这个安排直接证明恢复不依赖源服务仍在线。它没有模拟源盘永久损坏,但已经切断了回放时向源服务借数据的路径。

工具也需要可重建

固定服务器镜像是精简版本,真实CI发现其中没有mysqlbinlog。我们没有把退出码一百二十七忽略掉,而是补充官方8.4.11客户端RPM,下载后核对固定SHA-256,从中提取实际工具。工具镜像沿用同一固定基础镜像,记录mysqlbinlog版本,架构明确为linux/amd64。

提取阶段使用cpio读取RPM负载。cpio本身不是解释MySQL日志的程序;参与恢复语义的是已校验的mysqlbinlog可执行文件。工具镜像仍可能依赖基础系统动态库,所以沿用固定基础镜像,并实际运行版本和回放,避免只相信二进制已复制成功。ARM原生与其他发行版并未验证,读者应在对应环境重新执行。

完整性与连续性是两种检查

摘要验证某一个文件是否改变,连续性验证恢复范围内是否缺少文件或事件区间。假设三份归档各自摘要正确,但中间那份根本没有保存,仍然无法完整恢复。本书通过轮转把目标区间放在一个文件中,因此单文件覆盖能够清楚检查。生产应保存源实例身份、文件序列、起止位置和前后基线关联,不能只靠文件名字典排序。

归档还需要保存不可变性与读取权限。能删除生产数据的凭据不应天然也能删除所有历史副本;保存期限要覆盖故障发现延迟。加密会引入密钥可用性,压缩会引入解压工具和空间。每一种转换都要进入实际演练。本书原始二进制归档没有压缩加密,所以不声称证明了这些环节。

用真正缺失的文件做负例

程序临时把所需归档文件移走,然后仍用原来的目标路径请求mysqlbinlog。工具必须失败,pitr实例必须保持刚导入的基线状态,并且这份基线摘要确实不同于目标状态。这样才能证明“缺日志导致目标不可达”,而不是随便读取一个不存在且无关的文件,再把报错当作演练结果。

之后将文件放回原名,执行完全相同的恢复范围,才进入成功路径。负例与正例共享基线、开始位置、结束位置和必要文件,差异只有归档是否存在。这个结构让读者看清日志在恢复中的因果作用,也防止程序悄悄用源端数据补齐缺失输入。

归档完成不是恢复承诺终点

文件已复制并且hash匹配,证明它们是稳定输入;能被工具解析,证明格式基本可读;能回放到干净实例并得到正确业务状态,才证明目标可重建。每层证据都需要,任何单层都不能代替整体。下一章把范围进一步收紧到事务边界,避免一份完整归档被错误选择的结束位置破坏。

生产日志归档还应监控最后成功归档时间、未归档尾部大小、磁盘容量和保留删除。告警应描述缺口可能影响哪段业务确认,而不只说上传任务失败。只有把日志进度与恢复目标关联,值班人员才知道需要多久内处理,是否应暂停高风险批量操作。