DBAtlas · 数据库运维图谱

MySQL 复制日常运维与故障场景 (8.0 / 8.4)

MySQL难度: 高级耗时: 5 分钟(检查)– 2 小时(重建)

适用于已部署的 source + replica 拓扑(async / semi-sync,GTID 或 binlog 位置)的日常运维与故障恢复 runbook:健康与延迟检查、计划内 switchover、failover、将旧 source 重新加入、重建 replica(clone / XtraBackup / mysqldump)、errant GTID、1062/1032 错误、利用延迟 replica 恢复数据、迁移 replica 以及 binlog 清理。每个场景都按 诊断 → 安全网 → 执行 → 验证 → 后续 的顺序组织。这不是安装指南:首次搭建复制请打开«MySQL GTID 复制»指南,InnoDB Cluster (Group Replication) 请打开«InnoDB Cluster 运维»指南。

架构: 1 source + 1..5 replica (async / semi-sync)

场景

  • 状态与延迟检查(复制是否健康?) — 只读:检查 IO/SQL 线程、最近错误、真实延迟、semi-sync 状态和 errant GTID;不做任何更改,无停机。如果不确定该做什么,从这里开始:最后一步会根据输出指向正确的场景。
  • 计划内 switchover(将 source 角色移交给某个 replica) — source 和 replica 均健康;因维护、更换硬件或升级,需要按计划把 source 角色移交给某个 replica。写入会暂停几分钟,不丢数据;切回就是反向执行同一场景。
  • source 丢失:failover 到最领先的 replica — source 已崩溃或无法访问,且短时间内不会恢复(replica 上 IO 线程为 Connecting,2003/2013)。将最领先的 replica 提升为新 source,其余 replica 连接到它。在新 source 开放写入之前写入不可用;async 复制下 source 最后几个事务可能丢失。
  • failover 后将旧 source 作为 replica 重新加入 — 已完成 failover,旧 source 服务器恢复了。先禁止其写入并复制其 binlog,再检查 errant transaction;如果干净就直接作为 replica,否则从新 source 重建。新 source 无停机。
  • 从头重建 replica (clone / XtraBackup / mysqldump) — replica 所需的 binlog 已在 source 上被清除 (1236)、其数据已与 source 产生偏差、1062/1032 反复出现,或者 replica 的磁盘丢失。用 source 的副本替换 replica 的全部数据;source 保持在线,目标 replica 在此期间不可用。
  • Errant GTID:replica 上有 source 没有的事务 — 存在直接写入 replica 的事务(super_read_only 关闭期间),或旧 source 遗留的事务;failover 时这些事务会扩散到其他 replica,或以 1236 使复制停止。解决办法:空事务、在 source 上应用,或重建。无停机。
  • 复制停止:1062 Duplicate entry / 1032 Can't find record — SQL 线程因数据错误停止(Replica_SQL_Running: No,Last_SQL_Errno 1062/1032/1146/1677…)。先把该行修正为 source 上的状态;做不到时,作为最后手段跳过单个事务。只影响这个 replica:它会落后,从它读取的应用会看到旧数据。
  • 延迟 replica (SOURCE_DELAY):配置或恢复被删除的数据 — 需要让某个 replica 有意落后 N 秒(设置/取消延迟),或者在误删/误改的数据(DROP、不带 WHERE 的 DELETE/UPDATE)尚未在延迟 replica 上应用之前,从它那里找回数据。source 保持在线。
  • 将 replica 迁移到另一个 source(级联 / 重新指向) — 需要把某个 replica 挂到另一个 replica 之下(级联 / 中间 replica),或重新连回 source;不复制数据,只改变连接。被迁移的 replica 会停几秒钟。
  • binlog 清理与保留时间(磁盘将满) — binlog 正在占满磁盘,或者需要设置保留时间;在不删除 replica 和 PITR 仍需要的文件的前提下进行清理。无停机。

开始之前

  • 所有服务器均为 MySQL ……(8.0.26 及以后)… 且小版本相同…,gtid_mode = ON 且 enforce_gtid_consistency = ON…,binlog 已开启…;操作系统 root 可以用 mysql 免密连接(auth_socket 或 ~/.mylogin.cnf)。拓扑按照复制安装指南或同等方式搭建。
  • 已确认角色与输入一致:… (…)… 是丢失的旧 source… 是当前 source(read_only = 0,无 replica 配置)…,列表中的服务器为 replica。… failover 时被提升为 source 的是:… (…)。…
  • 已知 … 账号的密码。该账号已为每台服务器的 IP 创建('…'@'<ip>',REQUIRE SSL);各步骤用它读取其他服务器上的 GTID 集合等值,并在角色切换时用于复制连接。密码中不含 '、" 和 \。
  • 服务器之间可以通过 … 端口互相访问。
  • 所有服务器上两个 semi-sync 插件都已安装且为 ACTIVE:rpl_semi_sync_source (semisync_source.so) 和 rpl_semi_sync_replica (semisync_replica.so);角色切换时每台服务器的两端都会被开启或关闭。如果安装的是旧名称的 rpl_semi_sync_master / rpl_semi_sync_slave(8.0.26 之前,8.4 中已弃用),步骤中使用的 rpl_semi_sync_source_enabled / rpl_semi_sync_replica_enabled 变量不存在:先用 UNINSTALL PLUGIN 卸载旧插件再安装新插件(同一服务器上不能同时加载两者;只读服务器上 INSTALL PLUGIN 会被拒绝,需临时关闭 super_read_only)。
  • 在将成为新 source / 中间服务器的 replica 上,log_bin = ON 且 log_replica_updates = ON(8.x 默认);否则它的 binlog 不包含来自 source 的事务,其他 replica 无法连接到它。
  • 相关服务器之间有用于文件传输的 root SSH(密钥)访问…:… → ……。如果没有,请用组织批准的方式传输文件;各步骤会给出文件路径。
  • donor(…)和目标(…)上已安装与 MySQL 主版本相同的 Percona XtraBackup;donor 上有备份账号 bkpuser(auth_socket)——即 XtraBackup 指南的前两个阶段。
  • 变更审批和沟通渠道已就绪(应用团队、维护窗口)。角色切换时,已明确由谁、以何种方式修改应用的写入地址(VIP、DNS、ProxySQL / HAProxy / Router)。

指南阶段

  • 状态:source、replica 与延迟(只读) — 显示 source 的角色、binlog 位置和已连接的 replica · 显示各 replica 的线程状态、错误和延迟 · 从 performance_schema 测量真实延迟和应用队列 · errant GTID 检查(replica 上是否有 source 没有的事务?) · 解读结果并选择正确的场景
  • 1. 诊断:是否已具备 switchover 条件? — 检查 source 及已连接的 replica · 确认候选 replica 是否合适 · 检查所有 replica 是否健康
  • 2. 安全网 — 在所有服务器上记录当前状态
  • 3. 执行:移交角色 — 停止应用的写入 · 禁止 source 写入并获取最后位置 · 等待 replica 追上 source · 将候选者提升为 source (promote) · 将旧 source 设为新 source 的 replica · 将其他 replica 连接到新 source (…) …
  • 4. 验证 — 在新 source 上做测试写入 · 在所有服务器上检查复制和测试行
  • 5. 后续 — 删除测试数据库并更新运维配置
  • 1. 诊断:source 是否真的丢失?哪个 replica 最领先? — 最后一次尝试连接 source(从候选 replica) · 隔离旧 source (fencing) · 在每个 replica 上等待 relay log 中的事务应用完毕 · 确定最领先的 replica · 确定最领先的 replica(基于位置)
  • 2. 安全网 — 在 replica 上记录当前状态
  • 3. 执行:failover — 将候选者提升为 source (promote) · 将其他 replica 连接到新 source (…) · 在新 source 上开放写入 · 将应用重定向到新 source
  • 4. 验证 — 在新 source 上做测试写入 · 在 replica 上检查复制和测试行
  • 5. 后续 — 规划丢失的事务、备份和旧 source
  • 1. 诊断:旧 source 是否干净? — 显示旧 source 的状态 · 查找 errant transaction(与新 source 比较) · 基于位置复制时的重新加入决策
  • 2. 安全网 — 立即禁止旧 source 写入并记录其状态 · 将 errant transaction 导出到单独文件
  • 3. 执行:作为 replica 连接 — 将旧 source 连接到新 source
  • 4. 验证 — 确认旧 source 已作为 replica 运行
  • 5. 后续 — 规划拓扑和旧 source 的去向
  • 1. 诊断:errant 集合是什么? — 计算 errant GTID 集合
  • 2. 安全网:保存 errant transaction 的内容 — 从 binlog 解码 errant transaction 并保存
  • 3. 执行:在 source 上注入空事务 — 在 source 上将 errant GTID 作为空事务执行
  • 3. 执行:在 source 上应用 errant transaction — 将 errant transaction 导出到文件并复制到 source · 在 source 上应用这些事务
  • 4. 验证 — 确认 errant 集合已不存在
  • 5. 后续:防止再次发生 — 查找根本原因并保护 replica
  • 1. 诊断:哪个事务,哪一行? — 显示错误和失败的事务 · 从 relay log 解码失败事务的行 · 比较 source 和 replica 上的该行
  • 2. 安全网 — 记录 replica 状态和表的当前状态
  • 3. 执行:修正 replica 上的行 — 准备修正 SQL · 不写 binlog 地应用修正并启动复制
  • 3. 执行:跳过失败的事务(最后手段) — 只跳过失败的事务
  • 4. 验证 — 在两侧比较该行和表的校验和
  • 5. 后续 — 查找根本原因
  • 1. 诊断 — 显示 replica 当前的延迟设置
  • 2. 安全网 — 记录 replica 状态
按您的环境打开分步计划 →