Skip to content

MySQL GTID 复制

GTID 复制配置

前提条件

  • MySQL 版本:MySQL 5.6+ 支持 GTID 复制
  • 存储引擎:推荐使用 InnoDB 存储引擎
  • 二进制日志格式:必须使用 row 格式
  • 服务器 UUID:每个服务器必须有唯一的 UUID

主库配置

ini
# 启用二进制日志
log_bin = mysql-bin

# 设置服务器 ID
server_id = 1

# 启用 GTID
gtid_mode = ON
enforce_gtid_consistency = ON

# 使用 row 格式
binlog_format = row

# 保存 GTID 集合到表中
master_info_repository = TABLE
relay_log_info_repository = TABLE

# 自动清理中继日志
relay_log_recovery = ON

从库配置

ini
# 启用二进制日志(级联复制需要)
log_bin = mysql-bin

# 设置服务器 ID(必须与主库不同)
server_id = 2

# 启用 GTID
gtid_mode = ON
enforce_gtid_consistency = ON

# 使用 row 格式
binlog_format = row

# 保存 GTID 集合到表中
master_info_repository = TABLE
relay_log_info_repository = TABLE

# 自动清理中继日志
relay_log_recovery = ON

# 从库只读(可选)
read_only = ON

启动 GTID 复制

  1. 主库创建复制用户

    sql
    CREATE USER 'repl'@'%' IDENTIFIED BY 'password';
    GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
    FLUSH PRIVILEGES;
  2. 从库配置主库信息

    sql
    CHANGE MASTER TO
        MASTER_HOST = 'master_host',
        MASTER_PORT = 3306,
        MASTER_USER = 'repl',
        MASTER_PASSWORD = 'password',
        MASTER_AUTO_POSITION = 1;  -- 启用 GTID 自动定位
  3. 启动从库复制

    sql
    START SLAVE;
  4. 验证复制状态

    sql
    SHOW SLAVE STATUS\G
    • 检查 Slave_IO_RunningSlave_SQL_Running 是否为 Yes
    • 检查 Retrieved_Gtid_SetExecuted_Gtid_Set 是否包含 GTID 信息

GTID 复制管理

查看 GTID 信息

  • 查看当前服务器的 GTID 集合

    sql
    SHOW GLOBAL VARIABLES LIKE 'gtid_executed';
  • 查看正在进行的事务 GTID

    sql
    SELECT * FROM performance_schema.events_transactions_current WHERE GTID IS NOT NULL;
  • 查看二进制日志中的 GTID

    sql
    SHOW BINLOG EVENTS IN 'mysql-bin.000001';

跳过特定 GTID

  • 跳过单个 GTID

    sql
    STOP SLAVE;
    SET GTID_NEXT = 'uuid:sequence_id';
    BEGIN;
    COMMIT;
    SET GTID_NEXT = 'AUTOMATIC';
    START SLAVE;
  • 跳过多个 GTID

    sql
    STOP SLAVE;
    SET GLOBAL gtid_executed = CONCAT(@@GLOBAL.gtid_executed, ',uuid:sequence_id');
    START SLAVE;

重置 GTID

  • 重置主库 GTID

    sql
    RESET MASTER;  -- 清除所有二进制日志和 GTID 信息
  • 重置从库 GTID

    sql
    RESET SLAVE ALL;  -- 清除所有复制信息和 GTID 信息

GTID 复制监控

  • 监控复制延迟

    sql
    SELECT 
        NOW() - (SELECT TIMESTAMP FROM performance_schema.replication_connection_status) AS io_delay,
        NOW() - (SELECT TIMESTAMP FROM performance_schema.replication_applier_status) AS sql_delay;
  • 监控 GTID 执行情况

    sql
    SELECT 
        COUNT(*) AS total_transactions,
        COUNT(CASE WHEN GTID_SUBSET(gtid_executed, gtid_purged) THEN 1 END) AS executed_transactions
    FROM performance_schema.replication_connection_status;

GTID 复制最佳实践

配置最佳实践

  • 启用 GTID 一致性检查:确保所有事务都能被 GTID 正确跟踪
  • 使用表存储复制信息:提高复制的可靠性和崩溃恢复能力
  • 启用中继日志自动恢复:减少复制故障的恢复时间
  • 设置合理的二进制日志保留策略:避免磁盘空间耗尽

部署最佳实践

  • 使用唯一的服务器 ID:避免冲突和复制错误
  • 主库和从库配置一致:确保相同的 GTID 配置和二进制日志格式
  • 测试复制切换:定期测试故障转移和切换流程
  • 监控 GTID 集合:确保主从库的 GTID 集合保持一致

维护最佳实践

  • 定期备份 GTID 信息:包括 auto.cnf 文件和 GTID 集合
  • 避免手动跳过事务:除非必要,否则不要手动跳过 GTID 事务
  • 使用工具管理 GTID:如 MySQL Shell 或 MySQL Enterprise Monitor
  • 记录 GTID 相关操作:便于故障排查和审计

GTID 复制故障处理

常见故障类型

  • 复制延迟:从库执行事务落后于主库
  • 复制错误:从库执行事务失败
  • GTID 冲突:主从库的 GTID 集合不一致
  • 服务器 UUID 冲突:多个服务器使用相同的 UUID

复制错误处理

  • 查看错误信息

    sql
    SHOW SLAVE STATUS\G
  • 分析错误原因

    • 检查表结构不一致
    • 检查数据冲突
    • 检查权限问题
  • 修复方法

    • 跳过错误事务(如果允许)
    • 重新同步数据
    • 修复数据冲突后继续复制

GTID 集合不一致处理

  • 检查 GTID 集合

    sql
    -- 主库
    SHOW GLOBAL VARIABLES LIKE 'gtid_executed';
    
    -- 从库
    SHOW GLOBAL VARIABLES LIKE 'gtid_executed';
  • 重新同步数据

    1. 停止从库复制
    2. 使用 mysqldumpxtrabackup 从主库备份数据
    3. 恢复到从库
    4. 重新配置 GTID 复制
    5. 启动复制

服务器 UUID 冲突处理

  • 检查服务器 UUID

    sql
    SHOW VARIABLES LIKE 'server_uuid';
  • 修复 UUID 冲突

    1. 停止 MySQL 服务
    2. 删除 auto.cnf 文件
    3. 重启 MySQL 服务,自动生成新的 UUID
    4. 重新配置复制

GTID 复制高级特性

多源复制

  • 概念:一个从库可以同时从多个主库复制数据
  • 配置方法
    sql
    -- 配置第一个主库
    CHANGE MASTER TO
        MASTER_HOST = 'master1_host',
        MASTER_PORT = 3306,
        MASTER_USER = 'repl',
        MASTER_PASSWORD = 'password',
        MASTER_AUTO_POSITION = 1 
    FOR CHANNEL 'master1';
    
    -- 配置第二个主库
    CHANGE MASTER TO
        MASTER_HOST = 'master2_host',
        MASTER_PORT = 3306,
        MASTER_USER = 'repl',
        MASTER_PASSWORD = 'password',
        MASTER_AUTO_POSITION = 1 
    FOR CHANNEL 'master2';
    
    -- 启动所有通道
    START SLAVE FOR ALL CHANNELS;

级联复制

  • 概念:从库作为其他从库的主库,形成级联复制架构
  • 配置要点
    • 中间从库必须启用二进制日志
    • 中间从库必须设置 log_slave_updates = ON
    • 所有服务器必须启用 GTID

半同步复制与 GTID 结合

  • 配置方法
    ini
    # 主库配置
    plugin_load_add = 'rpl_semi_sync_master=semisync_master.so'
    plugin_load_add = 'rpl_semi_sync_slave=semisync_slave.so'
    rpl_semi_sync_master_enabled = 1
    rpl_semi_sync_master_timeout = 10000
    
    # 从库配置
    plugin_load_add = 'rpl_semi_sync_master=semisync_master.so'
    plugin_load_add = 'rpl_semi_sync_slave=semisync_slave.so'
    rpl_semi_sync_slave_enabled = 1

GTID 复制迁移

从传统复制迁移到 GTID 复制

  • 迁移步骤

    1. 确保所有服务器使用 MySQL 5.6+ 版本
    2. 配置主从库的 GTID 参数(不启用)
    3. 重启所有服务器
    4. 启用 GTID 模式
    5. 切换到 GTID 复制
  • 具体操作

    sql
    -- 步骤 1:配置参数
    SET GLOBAL gtid_mode = OFF_PERMISSIVE;
    SET GLOBAL enforce_gtid_consistency = WARN;
    
    -- 步骤 2:逐步启用
    SET GLOBAL enforce_gtid_consistency = ON;
    SET GLOBAL gtid_mode = ON_PERMISSIVE;
    
    -- 步骤 3:等待所有事务完成
    -- 检查是否还有使用传统复制的事务
    SELECT COUNT(*) FROM performance_schema.replication_applier_status WHERE SERVICE_STATE = 'ON' AND CHANNEL_NAME = '';
    
    -- 步骤 4:完全启用 GTID
    SET GLOBAL gtid_mode = ON;
    
    -- 步骤 5:切换到 GTID 复制
    STOP SLAVE;
    CHANGE MASTER TO MASTER_AUTO_POSITION = 1;
    START SLAVE;

GTID 复制升级

  • 升级注意事项

    • 先升级从库,再升级主库
    • 确保升级前后的 GTID 配置兼容
    • 测试升级后的复制功能
    • 准备回滚计划
  • 升级步骤

    1. 备份所有服务器的数据和配置
    2. 升级从库到新版本
    3. 验证从库功能正常
    4. 升级主库到新版本
    5. 验证主从复制正常

常见问题(FAQ)

Q1: GTID 复制比传统复制更慢吗?

A1: GTID 复制的性能与传统复制相当,甚至在某些场景下更快:

  • GTID 复制减少了复制位置管理的开销
  • 自动定位功能减少了复制配置和恢复的时间
  • 但在高并发场景下,GTID 生成和管理会带来轻微的开销

Q2: 如何处理 GTID 重复的问题?

A2: GTID 重复通常由以下原因引起:

  • 服务器 UUID 冲突
  • 手动修改 GTID 集合
  • 数据恢复不当

解决方法:

  • 确保每个服务器有唯一的 UUID
  • 避免手动修改 GTID 集合
  • 使用正确的方法恢复数据
  • 必要时重置 GTID

Q3: GTID 复制支持哪些复制拓扑?

A3: GTID 复制支持多种复制拓扑:

  • 一主一从
  • 一主多从
  • 级联复制
  • 多源复制
  • 环状复制(需谨慎使用)

Q4: 如何在 GTID 复制中添加新的从库?

A4: 可以通过以下方式添加新从库:

  1. 使用 mysqldump 备份主库(包含 GTID 信息)

    bash
    mysqldump --master-data=2 --single-transaction --triggers --routines --events --all-databases > backup.sql
  2. 恢复到新从库

    bash
    mysql < backup.sql
  3. 配置 GTID 复制

    sql
    CHANGE MASTER TO
        MASTER_HOST = 'master_host',
        MASTER_PORT = 3306,
        MASTER_USER = 'repl',
        MASTER_PASSWORD = 'password',
        MASTER_AUTO_POSITION = 1;
    
    START SLAVE;

Q5: GTID 复制中的事务顺序如何保证?

A5: GTID 复制通过以下机制保证事务顺序:

  • 每个事务被分配唯一的 GTID
  • 从库按照 GTID 的顺序执行事务
  • GTID 集合记录了事务的执行状态
  • 从库不会重复执行已有的 GTID

Q6: 如何监控 GTID 复制的健康状态?

A6: 可以通过以下方式监控:

  • 使用 SHOW SLAVE STATUS 查看复制状态
  • 监控 Retrieved_Gtid_SetExecuted_Gtid_Set 的差异
  • 使用 Performance Schema 监控复制事件
  • 结合 Prometheus + Grafana 进行可视化监控
  • 使用 MySQL Enterprise Monitor 进行专业监控