实验环境

此次实验的环境如下

  • MySQL 5.7.25

  • Redhat 6.10

  • 操作系统账号:mysql

  • 数据库复制账号:repl

  • 复制格式:基于行的复制

IP地址 主从关系 复制账号 复制格式
11.12.14.29 主库 repl Row-Based
11.12.14.30 从库(半同步) repl Row-Based
11.12.14.31 从库(异步) repl Row-Based

通过前面的介绍我们知道MySQL的复制有两种方法

  • 基于二进制日志文件位置
  • 基于GTID

上节内容为gtid_next和gtid_purged系统变

这节的内容为Auto-Positioning

1. 基于GTID的MySQL同步

通过第二节的内容我们知道主库和从库之间的复制通过日志名和位置点进行同步

如果启用了GTID,则可以使用GTID来进行同步

如果使用基于GTID的MySQL同步我们不需要在change master中使用MASTER_LOG_FILE 和MASTER_LOG_POS 参数,而是使用MASTER_AUTO_POSITION 选项,该选项默认是禁用的

2. GTID Auto-Positioning

当启用了GTID功能(GTID_MODE=ON, ON_PERMISSIVE, 或 OFF_PERMISSIVE),并且 MASTER_AUTO_POSITION被启用则表示在从库连接到主库时auto-positioning功能被激活了,同样的主库的GTID功能必须开启

接下来我们来看下auto-positioning是如何工作的

2.1 从库发送其已有GTID

在握手阶段,从库会向主库发送已经提交过的以及接收过的GTID集合

已经提交过的通过查询gtid_executed变量得出

1.png

已接收到的通过如下查询得出

SELECT RECEIVED_TRANSACTION_SET FROM PERFORMANCE_SCHEMA.replication_connection_status;
2.png

2.2 主库发送剩下的GTID事务

之后主库会向从库发送其二进制日志文件中所有事件,不包括从库发送过来的GTID的事务

这样就保证了主库不会发送从库已经拥有的GTID的事务

如果是多源复制(多个主库),则auto-skip会保证事务不会执行两次

以上就是MySQL的Auto-Positioning功能

3. 常见故障

如果任何应该被发送到从库的事务从二进制日志中清除了,或者在手动加入gtid_purged中了,则主库会发送一个ER_MASTER_HAS_PURGED_REQUIRED_GTIDS 错误到从库,这时复制不会被启动

这时可以禁用MASTER_AUTO_POSITION 选项之后重连,不过这时会出现数据丢失,建议有两种方法解决

  • 从另外位置获取该GTID事务
  • 使用最近的主库备份重新还原从库

如果在交换期间,从库接收到的事务在主库上没有,这时主库会发送一个ER_SLAVE_HAS_MORE_GTIDS_THAN_MASTER错误,之后复制不会启动

该问题一般发生在主库没有设置sync_binlog=1,这时如果发生服务器宕机,可能会导致事务未记录在二进制文件中,但是已经被传输到从库了

还有种错误就是主库和从库相同的GTID被分配了不同的事物,这时我们需要手动解决冲突或者将其中一个移出复制拓扑结构中

4. 参考资料

本专题内容翻译自官方文档并结合自己的环境

https://dev.mysql.com/doc/refman/5.7/en/replication-gtids-auto-positioning.html