PmaControl logo PmaControl
  • 首页
  • PmaControl
    • AI智能代理 13个本地代理
    • 定价方案 Community、Cloud、On-Premise、Premium
    • 文档 指南、API、架构
    • 插件市场 社区插件
    • 客户 28+企业
    • 常见问题 25个问题 / 7个类别
    数据库
    • MariaDB 31 篇文章
    • MySQL 11 篇文章
    • Galera Cluster 6 篇文章
    • MaxScale 3 篇文章
    • ProxySQL 2 篇文章
    • Amazon Aurora MySQL 0 篇文章
    • Azure Database 0 篇文章
    • ClickHouse 0 篇文章
    • GCP CloudSQL 0 篇文章
    • Percona Server 0 篇文章
    • SingleStore 0 篇文章
    • TiDB 0 篇文章
    • Vitess 0 篇文章
    解决方案
    • 全天候支持 MariaDB & MySQL紧急支持
    • Observabilité SQL 监控、告警、拓扑
    • Haute disponibilité 复制、故障转移、Galera
    • Disaster Recovery 备份、恢复、RPO/RTO
    • Sécurité & conformité 审计、GDPR、SOC2
    • Migration & upgrade 零停机、pt-osc、gh-ost
  • 定价方案
  • 资源
    • 文档 技术指南与API
    • MySQL 优化中心 Markdown 索引、指标、参数、故障
    • 常见问题 25个常见问题
    • 客户评价 客户反馈与案例
    • 博客 文章与洞察
    • 路线图 即将推出的功能
    专业领域
    • Observabilité SQL 监控、告警、Dot3拓扑
    • Haute disponibilité 复制、故障转移、Galera
    • Sécurité & conformité 审计、GDPR、SOC2、ISO 27001
    • Disaster Recovery 备份、恢复、RPO/RTO
    • Performance & optimisation Digests、EXPLAIN、调优
    • Migration & upgrade 零停机、pt-osc
    快速链接
    • GitHub Wiki 26页 — 安装、引擎、插件
    • 源代码 GitHub官方仓库
    • 全天候支持 MariaDB & MySQL紧急支持
    • 预约演示 30分钟 — 真实架构
  • 全天候支持
  • 预约演示
预约演示
🇫🇷 FR Français 🇬🇧 EN English 🇵🇱 PL Polski 🇷🇺 RU Русский 🇨🇳 ZH 中文 🇸🇦 AR العربية
← 返回博客

切换到 GTID 时为何会破坏复制

发布于 2026年5月18日 作者 Aurélien LEQUOY
mariadb mysql replication gtid binlog pmacontrol dba incident
分享 X LinkedIn Facebook Email PDF
切换到 GTID 时为何会破坏复制

现象

这个场景很常见:MariaDB 复制原本使用 file/position 模式,为了测试或增强复制连接而启用 GTID,然后又切回普通模式。几秒钟后,IO thread 无法启动:

SHOW SLAVE STATUS\G
Slave_IO_Running: No
Slave_SQL_Running: Yes
Using_Gtid: No
Last_IO_Errno: 1236
Last_IO_Error: Could not find first log file name in binary log index file

最容易想到的解释是:“切到 GTID 清理了 relay logs 或 binlogs”。在这次分析的事件中,事实并不是这样。

GTID 按钮实际做了什么

在 PmaControl 中,MariaDB 复制上的 GTID > Activate 操作不会执行 purge,也不会执行 RESET SLAVE。

它只执行:

STOP SLAVE;
CHANGE MASTER TO MASTER_USE_GTID = slave_pos;
START SLAVE;

回滚操作执行:

STOP SLAVE;
CHANGE MASTER TO MASTER_USE_GTID = no;
START SLAVE;

这些命令不会删除源端的 binlogs。但是,CHANGE MASTER 会重建本地复制状态,并重置副本上的 relay logs。这个区别很重要:源端没有丢失任何东西,但副本会丢弃它已经在本地下载的内容。

真实规模测试

为了验证这个行为,我在两台 MariaDB 11.8 实验服务器上复现了该场景:

source -> replica
初始为 file/position
relay_log_purge=ON

测试步骤:

  1. 启动一条干净的 file/position 复制;
  2. 只停止副本的 SQL thread;
  3. 在源端生成 20,000 行;
  4. 确认 IO thread 已经把事件下载到 relay logs;
  5. 执行与 GTID > Activate 按钮相同的序列。

在 CHANGE MASTER 之前,副本上存在尚未应用的 relay logs:

Slave_IO_Running: Yes
Slave_SQL_Running: No
Read_Master_Log_Pos: 635180
Exec_Master_Log_Pos: 3464
Relay_Log_Space: 632576
relay-bin.000002: 632273 bytes

执行 STOP SLAVE 后,没有丢失:

Slave_IO_Running: No
Slave_SQL_Running: No
Relay_Log_Space: 632576
relay-bin.000002: 632273 bytes

紧接着执行:

CHANGE MASTER TO MASTER_USE_GTID=slave_pos;

relay logs 被重置:

Using_Gtid: Slave_Pos
Read_Master_Log_Pos: 3464
Exec_Master_Log_Pos: 3464
Relay_Log_Space: 256
relay-bin.000001: 256 bytes

反向测试得到相同结果。在 GTID 模式下,如果存在尚未应用的 relay logs,通过:

CHANGE MASTER TO MASTER_USE_GTID=no;

回到 file/position,也会重置本地 relay logs。

测试结论:单独的 STOP SLAVE 会保留 relay logs。CHANGE MASTER 即使只修改 MASTER_USE_GTID,也会重置它们。

实际发生了什么

副本回到 file/position 模式时,保留下来的物理坐标太旧:

mariadb-bin.014786:35578691

relay source 的 binary log index 中已经没有这个文件。它当前第一个可用文件已经更新:

first available: mariadb-bin.015028
last available:  mariadb-bin.015130
retained files:  103
retained size:   about 10 GiB

而源端当时仍配置为:

binlog_expire_logs_seconds = 864000
expire_logs_days           = 10
binlog_space_limit         = 0
max_binlog_size            = 104857600

也就是说,当前配置显示“10 天”。但副本请求的坐标已经早于实际可用窗口。

为什么 10 天并不保证这个文件存在

10 天保留期意味着服务器可以清理早于该限制的 binlogs。它并不保证副本在切换模式后还能回到任意旧的物理坐标。

有几种情况会让问题变得危险:

  • 点击之前复制已经有延迟;
  • 副本在 GTID 期间保留了旧的 file/position 坐标;
  • 之前的 purge 已经删除了请求的文件;
  • retention 值过去可能被修改过;
  • maintenance 或 rebuild 可能重建了一个比预期更短的窗口;
  • upstream master 和 relay source 可能使用不同的策略。

关键点很简单:如果文件不在 SHOW BINARY LOGS 中,MariaDB 就无法提供它,即使当前配置显示 10 天。

为什么 GTID 掩盖了问题

在 MariaDB GTID 模式下,副本不再请求 MASTER_LOG_FILE / MASTER_LOG_POS 这一对物理坐标。它通过 gtid_slave_pos 请求逻辑事务集合。

当切回 file/position 时,旧的物理坐标再次变得重要。如果这些坐标指向一个已经被清理的文件,IO thread 会立即以 1236 失败。

GTID 没有清理源端 binlogs。但是,通过 CHANGE MASTER 进行切换确实删除了副本已经下载到本地的 relay logs。如果这些 relay logs 中的事务已经无法从源端 binlogs 再次获取,那么恢复就必须依赖重新同步。

为什么简单的 CHANGE MASTER 不够

一个常见尝试是把副本直接指向源端当前的位置:

STOP SLAVE;
CHANGE MASTER TO
  MASTER_LOG_FILE='mariadb-bin.015130',
  MASTER_LOG_POS=97211185,
  MASTER_USE_GTID=no;
START SLAVE;

IO thread 可能会重新启动。但 SQL thread 随后可能因为约束失败而停止,例如:

Last_SQL_Errno: 1452
Cannot add or update a child row:
foreign key constraint fails

这是符合预期的:直接跳到较新的位置会跳过一段事务。副本数据已经无法匹配它接下来收到的事件序列。

这不是修复,而是跳日志。

正确修复方式

可靠的修复方式是从一致的源重新同步副本:

  1. 停止复制;
  2. 从 source 或 relay source 获取一致性备份;
  3. 恢复副本;
  4. 获取备份对应的精确位置;
  5. 以 GTID 或 file/position 配置复制;
  6. 启动复制;
  7. 验证两个线程都正常。

期望结果:

Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Seconds_Behind_Master: 0 or decreasing
Last_IO_Error:
Last_SQL_Error:

这里不应使用 sql_slave_skip_counter。跳过外键错误只会掩盖数据分歧,并留下不一致的数据。

点击前应增加的检查

在启用或停用 GTID 之前,PmaControl 应该先回答三个问题:

SHOW SLAVE STATUS\G
SHOW BINARY LOGS;
SHOW VARIABLES WHERE Variable_name IN (
  'expire_logs_days',
  'binlog_expire_logs_seconds',
  'binlog_space_limit',
  'max_binlog_size'
);

然后确认:

  • 副本的 Relay_Master_Log_File 是否仍存在于源端?
  • 副本是否已经有延迟或错误?
  • binlog 窗口是否覆盖请求的位置?

如果答案是否定的,按钮就不应该只是发送 CHANGE MASTER。它应该显示警告并建议 rebuild。

结论

切换到 GTID 并没有清理源端 binlogs。但是,用于进入 GTID 并返回 file/position 的 CHANGE MASTER 重置了副本的本地 relay logs。

在健康环境中,副本会从源端重新下载这些事件。在这次分析的事件中,请求的坐标已经超出了源端 binlog 窗口。本地 relay logs 被丢弃后,就不再有任何来源可以重放缺失的事务范围。

运维上的教训很明确:在 GTID 和 file/position 之间切换之前,必须验证源端 binlog 窗口。否则,一个本应可回滚的测试会变成一次强制重新同步。

分享 X LinkedIn Facebook Email PDF
← 返回博客

评论 (0)

暂无评论。

发表评论

PmaControl
+33 6 63 28 27 47 contact@pmacontrol.com
法律声明 GitHub 联系我们
不要等到故障发生才了解您的架构。 © 2014-2026 PmaControl — 68Koncept