登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  MySQL

MySQL Clone 插件恢复后复制坐标如何衔接

来源:17golang原创

时间:2026-10-09 17:46:29 139浏览 收藏

我第一次用 MySQL Clone 给新副本铺数据时,真正让我犹豫的不是克隆命令,而是实例重启后的那几分钟:复制到底该从哪里接?是再去供体取一份“最新坐标”,还是在接收端执行 SHOW BINARY LOG STATUS,又或者沿用旧通道里的位置?

结论先说:Clone 已经把数据快照对应的一致性起点带到了接收端。恢复后应读取 performance_schema.clone_status,然后二选一:GTID 环境使用 SOURCE_AUTO_POSITION=1,文件位点环境使用其中的 BINLOG_FILE 与 BINLOG_POSITION。不要改用接收端自己的新二进制日志坐标,也不要为了“更新”而在克隆完成后重新取供体当前位点。

官方文档:https://dev.mysql.com/doc/refman/8.4/en/clone-plugin-replication.html

坐标从哪里来:Clone 已经冻结一致性起点

一次远程克隆不是“先复制一些文件,再随便找个日志位置”。MySQL 会把 InnoDB 数据快照与该快照对应的复制元数据一起传输。接收端得到的关键值有两套:文件名加偏移,以及供体的 gtid_executed。它们描述的是同一个一致性边界。

这里最容易混淆的是:坐标会传输,二进制日志文件本身不会传输。因此,克隆结束后的增量事务仍要从复制源的日志中取得。如果这段时间里所需日志被清理,复制握手就可能失败。我的做法是把“克隆完成”和“复制启动”当作同一项变更里的两个动作,提前核对日志保留窗口,不让它们隔太久。

MySQL Clone 供体快照、复制坐标元数据、接收端 clone_status 与供体二进制日志的静态边界关系图

图1:Clone 数据快照、复制坐标元数据与供体二进制日志之间的边界关系。

恢复后先核对 clone_status 与服务器配置

接收端重启后,我会先查最近一次克隆状态,而不是先改复制通道:

-- 查看当前或最近一次克隆的状态与两套复制坐标
SELECT STATE,
       SOURCE,
       ERROR_NO,
       ERROR_MESSAGE,
       BINLOG_FILE,
       BINLOG_POSITION,
       GTID_EXECUTED
FROM performance_schema.clone_status;

clone_status 只保存当前或最近一次克隆的一行记录,而且是只读表。看到 STATE 成功并不代表复制一定能直接启动,它只证明克隆阶段完成;真正的复制连接、账号权限、网络、TLS、通道配置和日志保留还要分别检查。

Clone 也不会复制服务器配置。接收端会保留自己的配置,包括持久化变量。因此至少要重新确认以下几项:

  • server_id 是否唯一,不能与复制拓扑中的其他实例重复;
  • gtid_mode 与计划采用的定位方式是否一致;
  • 复制账号、来源主机、端口、TLS 参数是否适用于新接收端;
  • 通道名、复制过滤规则和并行复制配置是否符合预期;
  • 实际复制源是否仍保留从克隆坐标开始的必要日志。

另外,Clone 只克隆 InnoDB 数据。若业务中还有其他存储引擎表,不能把“数据目录已恢复”理解成所有对象都已等价复制。

恢复后只选一种坐标模型

GTID 和文件位点都是合法路径,但一个通道在一次配置里应当明确选择一种。二者都从 clone_status 获得一致性依据,配置字段却不能混着用。

MySQL Clone 恢复后 GTID 自动定位与文件位点两种复制坐标模型的静态对照图

图2:GTID 自动定位与文件位点衔接共用 clone_status,但配置字段不能混用。

GTID 模式:让自动定位寻找缺失事务

如果接收端启用了 GTID,且供体的 GTID 模式满足官方支持条件,Clone 会把供体的 gtid_executed 应用到接收端。此时复制通道不需要手填文件名和偏移,使用自动定位即可。下面是一个新建或重配通道的模板:

-- 仅停止准备重配的通道,避免影响其他通道
STOP REPLICA FOR CHANNEL 'setup_channel';

-- GTID 模式只声明复制源与自动定位,不再填写文件位点
CHANGE REPLICATION SOURCE TO
  SOURCE_HOST = 'source.example.internal',
  SOURCE_PORT = 3306,
  SOURCE_AUTO_POSITION = 1
FOR CHANNEL 'setup_channel';

-- 示例口令是占位符,生产环境应使用受控凭据
START REPLICA
  USER = 'repl_user'
  PASSWORD = 'replace_with_secret'
FOR CHANNEL 'setup_channel';

如果供体本身就是副本,并且它原有通道采用 GTID 自动定位,那么这些通道在接收端启动后有机会直接续跑。实际操作中我仍会逐个核对通道,因为 Clone 不会替你判断新机器是否应该连接原来的上游,也不会替你审查复制过滤规则。

这里不建议照搬旧文章里的 RESET MASTER,也不要把 clone_status.GTID_EXECUTED 粗暴地改写成 gtid_purged。Clone 已经处理了快照对应的已执行集合,额外重置或改写 GTID 状态反而可能破坏一致性。

文件位点模式:使用克隆时记录的文件名与偏移

没有使用 GTID 时,就从查询结果中取出 BINLOG_FILE 和 BINLOG_POSITION。假设实际值分别为 mysql-bin.000842 与 3179551,配置模板如下:

-- 停止目标通道后,用 clone_status 的实际结果替换示例值
STOP REPLICA FOR CHANNEL 'setup_channel';

-- 文件位点模式使用克隆快照对应的源日志文件与偏移
CHANGE REPLICATION SOURCE TO
  SOURCE_HOST = 'source.example.internal',
  SOURCE_PORT = 3306,
  SOURCE_LOG_FILE = 'mysql-bin.000842',
  SOURCE_LOG_POS = 3179551
FOR CHANNEL 'setup_channel';

-- 启动目标通道,凭据应从安全渠道提供
START REPLICA
  USER = 'repl_user'
  PASSWORD = 'replace_with_secret'
FOR CHANNEL 'setup_channel';

不要把接收端执行 SHOW BINARY LOG STATUS 得到的值填进去。那是接收端本地新日志的坐标,描述的是它作为日志生产者的位置,不是供体快照的增量起点。同样,也不要在克隆结束后再取供体“此刻”的坐标;这样会跳过快照时刻到当前时刻之间的事务。

两个常见异常:日志已清理与中继日志恢复失败

供体已经清理所需二进制日志

数据快照虽然完整,但快照之后的增量仍依赖供体日志。如果 BINLOG_FILE 已被清理,文件位点复制无法接上;GTID 自动定位也要求你连接的复制源拥有接收端缺失事务的历史。此时不要随意把位置向前挪到现存日志,而应判断能否换到拥有完整历史的同拓扑节点;若不能,就需要重新克隆并在日志保留窗口内启动复制。

多线程副本无法自动恢复中继日志

文件位点模式下,已有通道会尝试利用克隆后的中继日志信息恢复。单线程副本在没有其他问题时通常能够恢复,而 replica_parallel_workers > 0 的多线程副本更可能失败。遇到这种情况,我不会反复启动通道碰运气,而是停止目标通道,回到 clone_status 的文件名与偏移,明确执行一次 CHANGE REPLICATION SOURCE TO。

重配时应只处理目标通道。多源复制环境尤其不要使用范围过大的重置命令,否则可能把其他正常通道的连接信息一并清除。

启动后的检查:线程正常不等于已经追平

启动后先看目标通道的实时状态:

-- 查看目标通道的 IO、SQL 线程、延迟与最后错误
SHOW REPLICA STATUS FOR CHANNEL 'setup_channel'\G

至少检查 Replica_IO_Running、Replica_SQL_Running、Last_IO_Error、Last_SQL_Error 和 Seconds_Behind_Source。GTID 模式还应关注已接收与已执行集合;文件位点模式则核对当前读取、执行位置是否持续向前。

我通常把收尾拆成三层:第一层是两条复制线程都运行;第二层是没有持续增长的错误或延迟;第三层是业务侧抽查关键表和只读流量。这样可以避免只凭一个 Yes/Yes 就宣布恢复完成。

简短判断表

  • 已经使用 GTID:读取并确认 GTID_EXECUTED,配置 SOURCE_AUTO_POSITION=1。
  • 仍使用文件位点:把 BINLOG_FILE 和 BINLOG_POSITION 原样用于目标通道。
  • 供体日志已清理:换用拥有完整历史的合适来源,或重新克隆;不要猜一个较新的位置。
  • 多线程副本恢复失败:停止目标通道,并用 clone_status 坐标手工重配。
  • 接收端本地日志有新坐标:忽略它,它不是这次恢复的上游复制起点。

把 Clone 理解成“数据快照 + 一致性坐标元数据”,这个问题就清楚了:数据落到接收端,坐标告诉复制从哪里补增量,而真正的增量日志仍留在复制源。恢复后的核心不是重新寻找一个看起来更新的位置,而是忠实地接住 Clone 已经保存的那个边界。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>